2012-04-23 209 views
1

在一个抽象的泛型类使用领域我在斯卡拉是这样的:初始化和斯卡拉

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中使用?

回答

7

您应该指定一个Input工具Point与通用型Type,因为就目前而言,不指定,它是作为Nothing(我猜编译器不能从setValue方法推断出它)考虑。所以,你必须做到以下几点:

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

更多信息

我回答的编译错误这个问题(它编译于斯卡拉2.9.0.1)。此外,我将此案例类视为现有类型的实现,如“Int”。在抽象类中_的使用当然是一个坏主意,但它并不是禁止的,但_并不总是空值,它是默认值,例如:var x:Int = _将赋值0x

+1

这个答案不正确。仅仅添加类型的情况下类,当他试图用'setValue'与除'Nothing'任何其它类型不会编译: '抽象类Point [T](n为字符串){ VAR值:T = _ VAL名称=正 } 情况下类输入[T](n为字符串)延伸点[T](N){ DEF的setValue(VA:T)=值= VA } 对象testTypedCaseClass { DEF测试(){ VAL富=输入( “foo” 的) foo.setValue( “条”) 的println(富) } }' RESU lts在: 'type mismatch;' 编译时 这是因为他在'Point [T]'中声明的值是'Nothing'。 – 2012-04-23 21:02:37

+0

不能相信我犯了这个简单的错误。事实上,这是错误的一部分,但如果我改变了这一点,并保留其余部分,它给了我同样的错误。 – 2012-04-23 21:10:59

+0

作为@JackViers提到的,使用默认值,再加上一些通用的类型为价值是相当混乱,这将实现默认值加上一个setter这是不是在同一层上,但我不把所有的代码,所以我建议一个简单的“补丁”。请毫不犹豫地在您的问题中提供更多细节。 – 2012-04-23 21:14:00

1

尝试以下操作:

包inputabstraction

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之外的任何内容,则会从上面得到类型不匹配,因为由于您使用了_,所以键入的值为Nothing

第三个错误是使用var而不是valdefvaldef可以互换覆盖,这意味着亚型可与valdef覆盖,和Scala编译器会看着办吧你。它是用来定义瓦尔斯如使用抽象类和特质def功能的最佳做法,因为亚型构造函数初始化顺序是一件很困难的事情得到正确的(没有为编译器如何确定如何从它的超类型构造一个类的algorithm )。 TL#DR ===在超类型中使用def。大小写类参数会自动生成val字段,由于您要扩展Point,因此将创建val值字段,该字段将覆盖Point[T]中的def值字段。

你可以摆脱这一切Type ||因为类型推断和Point是抽象的事实,因此可以通过val扩展值。

做的依赖注入这样的首选方式是cake pattern,但这个例子我已经提供了您的用例的作品。

+0

感谢您的解释。但是,如果我将value定义为'def value:Type',它会给我错误:'value value_ =不是test.package.Input [Type]的成员' – 2012-04-23 21:10:17

+0

T = Type。我相信类型抽象必须全部大写。当它们混合使用时,表示您正在使用特定类型:[S]正常。 [字符串]不是。 – 2012-04-23 21:26:49

+0

嗯......我不认为Scala是区分大小写的。 – 2012-04-23 21:28:24