2016-11-29 58 views
0

我試圖定義一個簡單的CRUD系統使用的基本特徵。但是,我需要基本特徵來支持「copyWithId」def(因爲Scala案例類的複製魔法不可用)。到目前爲止,我已經找到了最好的辦法是:定義一個scala特質def返回一個具體的子類型實例

trait Identifiable[ID, T] { 
    def id: Option[ID] 
    def copyWithId(id: Option[ID]): T 
} 

case class TestNamedIdentity(id: Option[Int], name: String) 
    extends Identifiable[Int, TestNamedIdentity] { 

    def copyWithId(id: Option[Int]): TestNamedIdentity = { 
    copy(id = id) 
    } 
} 

這工作,但因爲它需要所有的具體實例與ID和自我擴展看起來有點笨重。我想寫一些如下:

trait Identifiable[ID] { 
    this:X => 
    def copyWithId(id: Option[ID]): X 
    def id: Option[ID] 
} 

使用某種形式的自引用具體類。任何方式使這項工作?

更新:隨着使用情況如下

的想法是使用它的代碼就像

abstract class SomeClass[A <: IdentifiableEntity[ID], ID] { 
    def someFunc2: Option[ID] 
    def someFunc(item: A): A = { 
    item.copyWithId(someFunc2) 
    } 
} 

使用從@jwvh的解決方案需要調用後「asInstanceOf」鑄造。哪些用於我的用例,但希望得到更優雅的解決方案。

item.copyWithId(someFunc2).asInstanceOf[A] 
+1

第一種形式是唯一一個我知道需要寫一個涉及'Identifiable'也返回'T'參數化方法時很好地工作。重寫複製方法看起來很笨重,但對於我認爲更差的CRUD方法也是如此,所以我已經處理了它。除此之外,我能想到的最好的方法來保存一些樣板文件將是一個宏,但它只會節省很多。以抽象的方式處理「copy」是非常棘手的。 –

+0

@MichaelZajac我擔心宏將是唯一可行的解​​決方案,我不願意爲代碼庫添加這種級別的混淆。我認爲jwvh的方法對於api消費者來說至少比我上面的第一種形式更清晰。 – rapidninja

回答

1

這似乎工作。

trait Identifiable[ID] { 
    def id: Option[ID] 
    def copyWithId(id: Option[ID]): Identifiable[ID] 
} 

然後案例類被簡化。

case class TestNamedIdentity(id: Option[Int], name: String 
          ) extends Identifiable[Int] { 
    def copyWithId(id: Option[Int]): TestNamedIdentity = copy(id = id) 
} 
+0

然而,這樣做還是有效的,然後它需要任何用法來回避。例如:'saved.copyWithId(id).asInstanceOf [A]'。所以基本上交易一個樣板爲另一個。對於具體的用例,我正在處理這些作品。謝謝 – rapidninja

+1

@rapidninja,我沒有看到它。 copyWithId()的結果類型與case類中定義的一樣。爲什麼需要鑄造? 'saved.copyWithId()'應該與'saved'不同的類型嗎? – jwvh

+0

我將示例添加到原始帖子中以解釋用例以及爲什麼需要投射。 – rapidninja

相關問題