发布
社区首页 >问答首页 >在Scala中初始化和使用抽象泛型类中的字段

在Scala中初始化和使用抽象泛型类中的字段
EN

Stack Overflow用户
提问于 2012-04-24 03:24:47
回答 2查看 781关注 0票数 1

我在scala中有类似这样的东西:

代码语言:javascript
代码运行次数:0
复制
abstract class Point[Type](n: String){
    val name = n
    var value: Type = _
}

到目前一切尚好。问题出现在扩展Point的类中。

代码语言:javascript
代码运行次数:0
复制
case class Input[Type](n:String) extends Point(n){
    def setValue(va: Type) = value = va
}

setValue代码行上,我遇到了这个问题:

代码语言:javascript
代码运行次数:0
复制
[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中使用?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-24 03:33:54

您应该指定Input使用泛型类型Type实现Point,因为现在,由于没有指定它,它被认为是Nothing (我猜编译器不能从setValue方法中推断出它)。因此,您必须执行以下操作:

代码语言:javascript
代码运行次数:0
复制
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

票数 7
EN

Stack Overflow用户

发布于 2012-04-24 04:42:45

尝试以下操作:

包输入抽象

代码语言:javascript
代码运行次数:0
复制
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)
  }
}

一个简单的应用程序来检查它是否正常工作:

代码语言:javascript
代码运行次数:0
复制
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而不是valdef。scala和def可以互换覆盖,这意味着子类型可以用valdef覆盖,scala编译器会为您解决这个问题。最佳实践是在抽象类和特征中使用def将函数定义为函数,因为子类型构造函数的初始化顺序很难确定(编译器如何决定如何从其超类型构造类有一个algorithm )。TL#DR ===在超类型中使用def。Case类参数是自动生成的val字段,由于您正在扩展一个Point,因此它将创建一个val value字段,该字段覆盖Point[T]中的def value字段。

您可以在Scala中摆脱所有这些Type||T抽象,因为类型推断和Point是抽象的,因此使得值可以通过val扩展。

像这样做依赖注入的首选方法是cake pattern,但我提供的这个示例适用于您的用例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10286898

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档