我在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
我尝试用null
和null.asInstanceOf[Type]
进行初始化,但结果是一样的。
如何初始化值以便可以在setValue中使用?
发布于 2012-04-24 03:33:54
您应该指定Input
使用泛型类型Type
实现Point
,因为现在,由于没有指定它,它被认为是Nothing
(我猜编译器不能从setValue
方法中推断出它)。因此,您必须执行以下操作:
case class Input[Type](n:String) extends Point[Type](n){
def setValue(va: Type) = value = va
}
更多信息
我回答了这个问题的编译错误(它可以在scala 2.9.0.1上编译)。此外,我认为这个case类是现有类型的实现,比如'Int‘。在抽象类中使用_当然不是一个好主意,但这并不是禁止的,但是_并不总是null,它是默认值,例如:var x:Int = _
会将值0
赋给x
。
发布于 2012-04-24 04:42:45
尝试以下操作:
包输入抽象
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是您计划使用的类型。
第二个错误是您在这里定义和声明了值:t:var value: Type = _
。在此语句中,_
是一个值。它的值是Nothing
。scala编译器由此推断Point[T]
为Point[Nothing]
。因此,当您尝试将其设置为setValue
方法体中的类型时,必须将其设置为Nothing
,而这可能不是您想要的。如果您试图将它设置为除Nothing
之外的任何值,您将得到上面的类型不匹配,因为由于您使用了_
,value被类型化为Nothing
。
第三个错误是使用var
而不是val
或def
。scala和def
可以互换覆盖,这意味着子类型可以用val
或def
覆盖,scala编译器会为您解决这个问题。最佳实践是在抽象类和特征中使用def
将函数定义为函数,因为子类型构造函数的初始化顺序很难确定(编译器如何决定如何从其超类型构造类有一个algorithm )。TL#DR ===在超类型中使用def。Case类参数是自动生成的val
字段,由于您正在扩展一个Point,因此它将创建一个val value字段,该字段覆盖Point[T]
中的def value字段。
您可以在Scala中摆脱所有这些Type
||T
抽象,因为类型推断和Point
是抽象的,因此使得值可以通过val扩展。
像这样做依赖注入的首选方法是cake pattern,但我提供的这个示例适用于您的用例。
https://stackoverflow.com/questions/10286898
复制相似问题