假设我有一个基类
abstract class Base {
type B<: Base
def rep:String
def copy:B
}
class MyBase(override val rep:String) extends Base {
type B = MyBase
override def copy = new MyBase(rep)
}
然后我尝试添加另一个特性作为mixin,我希望复制的返回类型是合适的类型(意味着在mixin上调用copy会返回mixin类型,通过将B设置为适当的类型) 。我无法编译,甚至无法理解override关键字的位置。
编辑:我已经改进了示例
abstract class Base {
type B <: Base
def rep:String
def copy:B
}
class MyBase(val rep:String) extends Base {
type B = MyBase
def copy = new MyBase(rep)
}
trait DecBase extends Base {
abstract override def rep = "Rep: "+super.rep
}
我的问题是,如何为DecBase声明一个合适的B类和复制方法,以便该副本返回一个DecBase,而且,为什么不编译?
println(((new MyBase("ofer") with DecBase)).rep)
这是我在Java中可以实现的(有些肮脏,使用递归泛型类型)。我确信在Scala中可以做更好的事情。
修改
使用
trait DecBase extends Base {
override type B = DecBase
abstract override val rep= "Dec:"+super.rep
abstract override def copy = new MyBase(rep) with DecBase
}
我收到以下编译错误
error: overriding type B in class MyBase, which equals com.amadesa.scripts.MyBase;
type B in trait DecBase, which equals com.amadesa.scripts.DecBase has incompatible type
println(((new MyBase("ofer") with DecBase)).rep)
error: overriding type B in class MyBase, which equals com.amadesa.scripts.MyBase;
type B in trait DecBase, which equals com.amadesa.scripts.DecBase has incompatible type
abstract override def copy = new MyBase(rep) with DecBase
答案 0 :(得分:2)
我认为你的混音看起来像这样
trait MixIn extends Base {
override B = MixinBase
override def copy = new MixinBase(rep)
}
我认为override
上的MyBase
是问题的一部分。这是不必要的,并使编译器感到困惑。
如果copy
Base
实际上有一个实现,需要override
,你需要告诉编译器使用哪种方法。如果它不明显,它会抛出手并引发错误。试试这个。
val b = new MyBase(rep) with MixIn {
override def copy = MixIn.super.copy
}
MixIn.super.copy
是对您想要的人的调用。
您可能希望在Scala Class Linearization上查看此页面,以了解当您在某种类型中对方法进行竞争实施时会发生什么。
编辑:哦,这是一个完全不同的问题。它是case MyBase(val rep:String)
中的val。您不能使用def覆盖val,因为假定val是不可变的。您可以使用val覆盖def或var,但不能反过来。成功:
trait DecBase extends Base {
abstract override val rep = "Rep: "+super.rep
}
下次请包含编译错误。它使得查看问题变得容易得多。
答案 1 :(得分:0)
我认为它在某种程度上与班级val rep
中的MyBase
相关联。如果您不打算实施MyBase
,则应定义def rep
摘要。
以下是工作示例:
abstract class Base {
type B <: Base
def rep:String
def copy: B
}
class MyBase(val repVal: String) extends Base {
type B = MyBase
def rep = repVal
def copy = new MyBase(repVal)
}
trait DecBase extends Base {
abstract override def rep = "Rep: " + super.rep
}
println(((new MyBase("ofer"))).rep) // prints: ofer
println(((new MyBase("ofer") with DecBase)).rep) // prints: Rep: ofer
希望这有帮助。
答案 2 :(得分:0)
据我所知,目标是能够做到:
val myBase: MyBase = new MyBase("alone")
val myBaseCopy: MyBase = myBase.copy
val decBase: DecBase = new MyBase("mixed") with DecBase
val decBaseCopy: DecBase = decBase.copy
让我们重写您的代码以在type
声明中使用类型边界而不是相等(并且还要修复隐藏其他编译器错误的val rep
和def rep
之间的不匹配):
abstract class Base {
type B <: Base
def rep: String
def copy: B
}
class MyBase(_rep: String) extends Base {
type B <: MyBase
def rep = _rep
def copy = new MyBase(rep)
}
trait DecBase extends Base {
override type B <: DecBase
override abstract def rep = "Rep: " + super.rep
}
现在说MyBase.copy
应该返回MyBase
或子类,而DecBase.copy
应该返回DecBase
或子类。我相信这就是你想要的,对吧?现在产生的编译器错误很明显:
temp.scala:10: error: type mismatch;
found : this.MyBase
required: MyBase.this.B
def copy = new MyBase(rep)
^
one error found
所以你要返回MyBase
,但你真的需要返回子类,例如您希望返回new MyBase(rep) with DecBase
而不是new MyBase(rep)
,但仅当您的对象被声明为new MyBase(...) with DecBase
时。我不知道如何做到这一点,不过你可能会看adding a trait after an object has been constructed。