2011-02-01 151 views
6

假設我有一個基類性狀和抽象類型

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) 
} 

然後我嘗試添加另一種特質的混入,爲此,我要返回類型的副本是合適的類型(這意味着調用通過將B設置爲適當的類型,在mixin上覆制返回一個混合類型)。我一直無法得到這個編譯,甚至無法理解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 
} 

我的問題是,我怎麼聲明合適的B型和複印方法DecBase,因此複製返回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 

回答

2

我假設你的組合中看起來像這樣

trait MixIn extends Base { 
    override B = MixinBase 
    override def copy = new MixinBase(rep) 
} 

我認爲MyBase上的override是問題的一部分。這是沒有必要的,並使編譯器感到困惑。

如果copyBase實際上有一個實現,使得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 
} 

下次請包括編譯器錯誤。它使得查看問題更加容易。

+0

我已經完善了這個問題。 – user44242 2011-02-01 16:16:20

+0

再次編輯,這次添加編譯器錯誤。對我來說重要的是複製方法的正確返回類型。 – user44242 2011-02-01 16:56:06

+0

現在我無法正常工作。首先,您不能將B重寫爲DecBase,因爲DecBase不是MyBase的子類型。但修復後,我仍然收到錯誤。編譯器似乎不喜歡重寫類型B = MyBase,但也可能是別的。 – sblundy 2011-02-01 17:18:27

0

我認爲它在MyBase中以某種方式連接到val rep。你應該定義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 

希望這有助於。

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 SH應該返回一個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