2012-05-04 35 views
0

我想從超類(Tree[A])調用子類的構造函數來創建類型爲APartProject)的子類的其他實例。似乎肯定有一種方法比創建中間方法newChild的混亂更好,因爲像List這樣的工作。我聽說CanBuildFrom可能會解決這個問題。從工作中如何爲超類中的成員使用Scala子類構造函數?

提取物:

abstract class Tree[A](parent: Option[A], key: Int) { 
    protected def newChild(aKey: Int): A 
    lazy val children: List[A] = childrenOf.map(newChild(_)) 
    ... 
    } 

case class Part(parent: Option[Part], key: Int) extends Tree[Part](parent, key) { 
    protected def newChild(aKey: Int) = Part(Some(this), aKey) 
    ... 
    } 

case class Project(parent: Option[Project], key: Int) extends Tree[Project](parent, key) { 
    protected def newChild(aKey: Int) = Project(Some(this), aKey) 
    ... 
    } 
... 
"*" #> <ul>{Part(None, pKey).expandAsHtml}</ul> 

什麼是超類中使用Scala的子類構造函數的成員更好的辦法?

+5

你不應該顛倒那個邏輯並從子類構造函數調用超類的構造函數嗎?這是知道按照什麼順序做的事情的子類,而不是超類。 – geekosaur

+1

我很困惑。這段代碼是否編譯?如果編譯,哪些代碼不能編譯?什麼是錯誤消息(完整的錯誤消息,包括代碼行和列指示符)? –

+0

@DCS添加了「從工作代碼中提取」的提示。 –

回答

1

你正在向後看。當一個對象被創建時,它的構造函數被調用;這會默認或通過顯式調用委託給它的父類的構造函數。你不能從超類的構造函數中調用子類的構造函數,因爲它是子類的構造函數,它首先調用超類的構造函數。

你需要看看你的邏輯,記住子類已知的方式是被直接實例化;並不是超類作爲某種參數被實例化爲子類,而是超類被實例化爲實例化子類的一個步驟,並且超類應該只知道它自己的結構,而將子類細節留給觸發子類的構造函數超類。

+0

我相信超級類的(''')構造函數在延長線中被調用。然後,「children」的值將實例化子類的新不同實例(「Project」或「Part」)。 'newChild'是爲了完成它的工作而編造的,但它需要每個子類來實現它。似乎應該有一種方法來調用另一個子類實例的構造函數。 您的答案意味着它不能完成或不應該完成? –

+0

不完全; 'extend'告訴它爲所有的子類構造函數添加一個超類構造函數的調用,如果其中還沒有。你是說在構建一個特定的子類實例時,你想觸發另一個類似/同級實例的創建?無論如何,這仍然屬於子類,而不是超類。 – geekosaur

+0

每個實例都有'List [A]'類型的'val children'。列表中的每個實例都包含一個「children」列表...超類的目的是從子類中移除樹的實現細節(作爲List [A])。到超級班的一個共同的地方。 –

0

據我所知,實現這一目標的唯一方法是使用反射。

我發現了一個教程在這裏:http://www.heimetli.ch/java/create-new-instance.html

這樣你就可以得到你的超類中的子類的構造函數,並調用它來創建你的子類的新實例。

但是,您不知何故必須確保您的子類實現具有特定參數列表的構造函數。

相關問題