5

私はこれをしたい:

abstract class Context {
    def getInt(id: Int): Int
}

abstract class Dependency[+T]
(val name: String, val id: Int)
extends Function1[Context,T]

class IntDependency(name: String, id: Int)
extends Dependency[Int](name, id) {
    def apply(implicit context: Context): Int =
        context.getInt(id)
}

しかし、次のようなエラー メッセージが表示されます。

class IntDependency needs to be abstract, since method apply in trait
Function1 of type (v1: Context)Long is not defined (Note that T1 does
not match Context)

Implicit は通常、2 番目のパラメーター リストの一部であるべきであることは理解していますが、それをコンパイルして必要な結果が得られるようにコーディングする方法がわかりません。

説明: 他の関数に依存して値を計算できる「関数」オブジェクトを定義できるフレームワークを作成しようとしています。すべての関数は、1 つの Context パラメーターのみを受け取る必要があります。コンテキストは、他の関数の「結果」を知っています。関数インスタンスは不変であり、状態はコンテキストに存在する必要があります。関数が作成時に「依存関係」フィールドを作成し、暗黙的にコンテキストを取得し、そのコンテキスト内で依存関係の値を返すようにして、適用メソッド内の依存関係にアクセスすると、パラメーターまたはフィールドにアクセスするように感じます。 、つまり、コンテキストをパラメーターとして依存関係に明示的に指定することはありません。

4

4 に答える 4

5

Dependency延長する必要がありますFunctionか?そうしない場合は、そのextends Function1[Context,T]部分を除外するだけで、コードが機能するからです。

あなたが本当にFunctionあなたの場合の解決策を知らないよりも拡張する必要がある場合。applyただし、メソッドをオーバーロードしようとする場合があります。ここみたいに:

scala> val sum = new Function1[Int, Function1[Int, Int]] {
         |      def apply(a: Int) = (b: Int) => a + b
         |      def apply(a: Int)(implicit b: Int) = a + b
         |}
sum: java.lang.Object with (Int) => (Int) => Int{def apply(a:Int)(implicit b: Int): Int} = <function1>

scala> sum(2)(3)
res0: Int = 5

scala> implicit val b = 10
b: Int = 10

scala> sum(2)
res1: Int = 12
于 2011-06-19T10:51:21.793 に答える
4

メソッドは、暗黙的にマークされた最終パラメーター セクションを持つことができます。2 番目のセクションである必要はありませんが、これが最も一般的に見られます。

しかし、サブクラスがパラメーター セクションを暗黙的にマークすると、スーパークラスのメソッドをオーバーライドするとは見なされなくなったようです。

scala> new (Int => Int) { def apply(implicit i: Int) = i }
<console>:8: error: object creation impossible, since method apply in trait Function1 of type (v1: Int)Int is not defined
(Note that T1 does not match Int)
       new (Int => Int) { def apply(implicit i: Int) = i }
           ^

scala> trait F1 { def f(a: Any) }; new F1 { def f(implicit a: Any) = () }
<console>:8: error: object creation impossible, since method f in trait F1 of type (a: Any)Unit is not defined
       trait F1 { def f(a: Any) }; new F1 { def f(implicit a: Any) = () }

                                       ^

仕様ではこれについて特に言及されていないため (§5.1.4 オーバーライド)、実装上の制限またはバグである可能性があります。

于 2011-06-19T10:21:45.090 に答える
2

applyのメソッド署名がimplicitの署名に準拠していないことは確かですFunction1.apply。うまくいけば、私はあなたの問題を正しく解決するのでcontext、作成時に暗黙のコンテキストを注入することはどうですか? あなたの場合、それは可能ですか?

class IntDependency(id: Int)(implicit context: Context) extends Dependency[Int](id)

contextしかし、その後、メソッドの引数をどうするか疑問に思います (以前はまだ疑問に思っていました) apply

于 2011-06-19T10:22:47.617 に答える
2

実用的なソリューションは次のとおりです。

abstract class Context {
    def getInt(id: Int): Int
}

abstract class Dependency[+T]
(val name: String, val id: Int) {
    def get(context: Context): T
}

class IntDependency(name: String, id: Int)
extends Dependency[Int](name, id) {
    def get(context: Context): Int =
        context.getInt(id)
}

implicit def intDep2Int(dep: IntDependency)
(implicit context: Context): Int =
dep.get(context)
于 2011-06-19T11:36:03.940 に答える