Go 中的脆弱基類問題:微妙的差異
儘管將組合而非繼承作為設計原則,但問題依然存在: Go 中存在脆弱基類問題嗎?
定義脆弱基類問題
當基類的改變影響其衍生類時,就會出現脆弱基類問題意想不到的方式。這是由於多態性而發生的,而衍生類別中的方法可以覆寫基底類別中的方法。如果隨後修改基底類別方法,可能會無意中破壞衍生類別的行為。
Go 對問題的看法
在 Go 中,由於缺乏多態性缺乏虛擬方法。相反,Go 使用嵌入,其中一個結構可以包含另一個結構並直接存取其方法。雖然這種方法消除了脆弱基類問題的直接影響,但它引入了微妙的細微差別。
嵌入和方法提升
當嵌入一個結構體時,它的所有方法被提升到封閉的結構。但是,這些方法不能在封閉結構中被重寫。相反,可以新增具有相同名稱的新方法,但從嵌入結構中呼叫提升的方法仍將呼叫原始定義。
上下文中的範例
讓我們考慮以下示範脆弱基類問題的Java 範例:
<code class="java">class Counter { int value; void inc() { value++; } void incBy(int n) { value += n; } } class MyCounter extends Counter { @Override void inc() { incBy(1); } }</code>
這裡,修改Counter.incBy () 來迭代並呼叫inc() 會破壞MyCounter.inc(),進而導致無限迴圈。
然而,在 Go 中,由於缺乏多態性,類似的例子不會導致這樣的中斷。嵌入的 Counter 方法無法被覆寫,因此無論呼叫上下文如何,原始 Counter.Inc() 方法都將始終被呼叫。
<code class="go">type Counter struct { value int } func (c *Counter) Inc() { c.value++ } func (c *Counter) IncBy(n int) { c.value += n } type MyCounter struct { Counter } func (m *MyCounter) Inc() { m.IncBy(1) }</code>
在這種情況下,修改 Counter.IncBy() 不會影響MyCounter.Inc(),它將繼續增加計數器 1。
結論
Go 緩解了缺乏虛方法而導致的脆弱基類問題,它並沒有完全消除它。嵌入過程中方法的提升引入了問題的微妙形式。然而,與經典的脆弱基類問題相比,這種細微差別的破壞性更小,更可預測。
以上是Go 的嵌入方法是否消除了脆弱基類問題?的詳細內容。更多資訊請關注PHP中文網其他相關文章!