1

私はscalaにこのようなものを持っています:

abstract class Point[Type](n: String){
    val name = n
    var value: Type = _
}

ここまでは順調ですね。問題は、Pointを拡張するクラスにあります。

case class Input[Type](n:String) extends Point(n){
    def setValue(va: Type) = value = va
}

setValue回線上で私はこの問題を抱えています:

[error]  type mismatch;
[error]  found   : va.type (with underlying type Type)
[error]  required: Nothing
[error]   def setValue(va: Type) = value = va

で初期化しようとしましnullnull.asInstanceOf[Type]が、結果は同じです。

setValueで使用できるように値を初期化するにはどうすればよいですか?

4

2 に答える 2

7

今のところ指定されていないため、ジェネリック型でInput実装することを指定する必要があります(コンパイラはメソッドからそれを推測できないと思います)。したがって、次のことを行う必要があります。PointTypeNothingsetValue

case class Input[Type](n:String) extends Point[Type](n){
  def setValue(va: Type) = value = va
}

詳しくは

コンパイルエラーについてこの質問に答えました(scala 2.9.0.1でコンパイルされます)。さらに、このケース クラスは、'Int' などの既存の型の実装と見なされます。もちろん、_ の使用は抽象クラスでは悪い考えですが、禁止されているわけではありませんが、_ は常に null であるとは限りません。たとえば、デフォルトvar x:Int = _0ですx

于 2012-04-23T19:33:53.857 に答える
1

次のことを試してください。

パッケージ入力の抽象化

abstract class Point[T](n:String){
  def value: T
  val name = n
}

case class Input[T](n:String, value:T) extends Point[T](n)

object testTypedCaseClass{
  def test(){
    val foo = Input("foo", "bar")
    println(foo)
  }
}

それが機能することを確認するための簡単なアプリケーション:

import inputabstraction._


object TestApp extends Application{
  testTypedCaseClass.test()  
}

説明

あなたが犯している最初の間違いはcase class Input[Type](n:String) extends Point(n){. Point は型付きクラスであるため、 でスーパークラス コンストラクターを呼び出す場合はextends Point(n)、 の型を指定する必要がありますPoint。これは次のように行われます: extends Point[T](n)T は、使用する予定のタイプです。

2 番目のエラーは、 value:T here: の定義と宣言の両方を行っていることですvar value: Type = _。このステートメントで_は、 は値です。その値はNothingです。scala コンパイラは、これから を推論しPoint[T]ますPoint[Nothing]。したがって、メソッドの本体で型に設定しようとすると、 に設定setValueする必要がありますがNothing、これはおそらく望んでいるものではありません。以外の値に設定しようとするとNothing、上記の型の不一致が発生Nothingします_

3 番目の間違いは、 orvarの代わりに使用しています。 とは交換可能にオーバーライドできます。つまり、サブタイプは または のいずれかでオーバーライドでき、scala コンパイラがそれを見つけ出します。サブタイプ コンストラクターの初期化順序を正しく設定するのは非常に難しいため、vals を抽象クラスとトレイトで使用する関数として定義することをお勧めします(コンパイラーがそのスーパータイプからクラスを構築する方法を決定する方法に関するアルゴリズムがあります)。 . TL#DR === スーパータイプで def を使用します。ケース クラス パラメータは自動的に生成されるフィールドであり、Point を拡張しているため、 の def 値フィールドをオーバーライドする val 値フィールドが作成されます。valdefvaldefvaldefdefvalPoint[T]

||このすべてを回避できますType|| T型推論と抽象であるという事実のため、Scala でのPoint抽象化は、val を介して値を拡張可能にします。

このような依存性注入を行う好ましい方法はcake patternですが、私が提供したこの例はあなたのユースケースに適しています。

于 2012-04-23T20:42:44.947 に答える