2013-05-20 51 views
1

情況:案例類和繼承:如何提供不同的行爲

trait Operation { 
def something: Double 
} 

trait OperationPlus { this: A => 
override def something: Double = x + y 
} 
trait OperationMinus { this: A => 
    override def something: Double = x - y 
} 

case class A(x: Double, y: Double) { this: Operation => 
} 

val a = new A(1.0, 2.0) with OperationPlus 
    println(a.something) 

錯誤:

class A cannot be instantiated because it does not conform to its self-type A with Operation 

而且,我不能實例A.

我嘗試多種不同的方法,但沒有提供我在找什麼。我不想使用案例類繼承,或放棄案例類,理想情況下特質/自我類型/其他應該做的伎倆。有任何想法嗎?

更新 優選溶液

trait Operation { this: A => 
def something: Double 
} 

trait OperationPlus extends Operation { this: A => 
    override def something: Double = x + y 
} 
trait OperationMinus extends Operation { this: A => 
    override def something: Double = x - y 
} 

abstract case class A(val x: Double, val y: Double) extends Operation 

val a = new A(1.0, 2.0) with OperationPlus 
println(a.something) 

val b = new A(1.0, 2.0) with OperationMinus 
println(b.something) 

可能的解決方案1:

trait Operation { 
    def x:Double 
    def y:Double 
    def something: Double 
} 

trait OperationPlus extends Operation { 
    override def something: Double = x + y 
} 
trait OperationMinus extends Operation { 
     override def something: Double = x - y 
} 

abstract case class A(val x: Double, val y: Double) extends Operation 

通過使用常規類,簡單性狀遺傳和自型中的實際值可以定義它並動態地提供行爲。

不幸的是,我不得不重新定義特質中的字段。我想是公平的妥協。會有興趣知道是否有人知道另一種方法。

感謝

回答

2

不知道關於你的使用情況,但你需要定義A類這樣的,如果你想使其工作:

abstract case class A(x: Double, y: Double) extends Operation 

但我不認爲這是非常地道的做法用例類。它們主要用作數據容器,通常不包含任何行爲。 (也許你可以告訴一些事情的更多信息,你想用這個來實現)

+0

感謝@tenshi,如果我做的情況下抽象類,我將無法進行實例化。我想要做的是一個經典的面向對象的父類,併爲每個子類定義一個方法。然而,這些方法可以被不同的層次重複使用,所以我想使它成爲一個基本特徵。我無法找到如何提取出來。 – fracca

+0

@fracca你仍然可以通過在一些操作中混合實例化:'new A(1.0,2.0)和OperationMinus'。但是在你的示例方法中,'something'是抽象的,所以你需要定義它或者讓整個類變得抽象。或者,您可以直接在'A'類中擴展'OperationMinus'或'OperationPlus',並且不要聲明它是抽象的。 – tenshi

+0

抽象案例類有效地允許我們保留案例類的好處加上行爲混合。但是,因爲某些操作是基於A定義的,所以我需要重新定義字段x和y。 – fracca

2

首先,你應該有:

trait OperationPlus extends Operation 
trait OperationMinus extends Operation 

其次,你不能定義A作爲案例類,因爲這自動定義apply方法在伴隨對象上,其中new A被調用(帶參數)。由於錯誤的自我類型(您看到的錯誤),此調用失敗。

刪除case。如果你需要模式匹配,定義自己的提取(實施unapply):

class A(val x: Double, val y: Double) { this: Operation => } 

object A { 
    def unapply(v: A) = Some((v.x, v.y)) 
}