2013-08-20 43 views
1

問題不在於關於AnyRef.clone(),而是關於類似語義的情況。scala中類似可克隆性狀的正確類型規範

我想定義一個接口,可以自身創造副本類:

trait Cloneable { 
    def clone() : this.type 
} 

class Test(val store : Int) extends Cloneable { 
    def clone() = new Test(store) 
} 

路徑依賴,因爲this.typethis.type是行不通對於Test類類型和擴展一個類不同Test。後代應該重寫克隆方法以匹配它自己的類型。

我應該如何定義Cloneable特徵的類型要求?

我已經偷看到斯卡拉集合,並在這裏找到提示:定義TestLike性狀,處理類型限制,和類Test體現相應的特質。

我想,以避免不必要的笨拙,如果所建議的可能


試圖自循環模式:

trait Cloneable[A <: Cloneable[A]] { 
    def clone() : A 
} 

class Store[A <: Cloneable[A]](val store : Int) extends Cloneable[A] { 
    override def clone() : A = new Store[A](store) 
} 

失敗,出現錯誤:

Cloneable.scala:6: error: type mismatch; 
found : Store[A] 
required: A 
    override def clone() : A = new Store[A](store) 

反覆出現的另一個問題emplate:過早終結

class Store(val store : Int) extends Cloneable[Store] { 
    override def clone() = new Store(store) 
} 

class SubStore(store : Int, val stash : Double) extends Store(store) 

val ss1 = new SubStore(1, 0.5) 
val ss2 = ss1.clone() 
assert(ss2.isInstanceOf[SubStore]) 

問題與SubStore是與類型系統忽略不存在clone()方法在SubStore類雖然SubStore是經由StoreCloneable後代。但Store敲定Cloneable接口類型參數Store及其所有後代缺乏適當的clone()方法限制

+0

不是很漂亮,但斯卡拉版本的C++「CRTP」(奇怪的循環模板模式):特質Cloneable [A:

+0

我有一個應用週期性模板模式的問題,並將其發佈到更新後的任務中 – ayvango

+0

'class Store extends Cloneable [Store]','override def clone():Store' – senia

回答

0

斯卡拉類型差異允許你實現你一個簡單的方法所需要的,但你必須擺脫繼承路程,去的類型類。

trait Cloner[A]{ 
    def cloneObject(input:A):A 
} 
trait CloningFunctions{ 
    def cloneObject[A](input:A)(implicit cloner:Cloner[A]) = cloner.cloneObject(input) 
} 

object CloningFunctions extends CloningFunctions 

class MyClass1(val b:Int) 
class MyClass2(val a:Int,b:Int) extends MyClass1(b) 

object Example { 

    implicit val cloner = new Cloner[MyClass1]{ 
    def cloneObject(input: MyClass1): MyClass1 = new MyClass1(input.b) 
    } 

    import CloningFunctions._ 

    cloneObject(new MyClass2(3,4)) 

} 

這裏的想法是,既然克隆[A]是A型不變,下面的代碼不會編譯:

找不到參數拷貝機隱含值:克隆[MyClass2] CLONEOBJECT (new MyClass2(3,4))

因爲您有一個Cloner [MyClass1],但不是範圍內的Cloner [MyClass2]。

cloneObject(new MyClass1(3))將編譯。