尝试以下操作:
包输入抽象
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 是您计划使用的类型。
第二个错误是您在此处定义和声明 value:T: var value: Type = _
。在这个语句中,_
是一个值。它的值为Nothing
。Point[T]
scala 编译器由此推断出Point[Nothing]
. 因此,当您尝试将其设置为setValue
方法主体中的类型时,您必须将其设置为Nothing
,这可能不是您想要的。如果您尝试将其设置为除 之外的任何内容Nothing
,您将从上面得到类型不匹配,因为Nothing
由于您使用了_
.
第三个错误是使用var
代替val
或def
。 val
anddef
可以互换覆盖,这意味着子类型可以用val
or覆盖def
,scala 编译器会为你解决这个问题。将 val 定义为def
在抽象类和特征中使用的函数是最佳实践,因为子类型构造函数的初始化顺序很难正确处理(编译器如何决定如何从其超类型构造类有一个算法) . TL#DR === 在超类型中使用 def。案例类参数是自动生成的val
字段,由于您正在扩展一个点,因此将创建一个 val 值字段,该字段将覆盖Point[T]
.
你可以摆脱这一切Type
|| T
Scala 中的抽象是因为类型推断和抽象的事实Point
,因此可以通过 val 扩展值。
像这样进行依赖注入的首选方法是cake pattern,但我提供的这个示例适用于您的用例。