Go 中的脆弱基類問題:儘管組合優於繼承
當對基類的更改可能導致意外時,就會出現脆弱基底類別問題衍生類別中的行為。這個問題通常歸因於繼承,而衍生類別繼承其基底類別的方法和字段。
Go 中沒有實作繼承。相反,Go 使用組合,其中一個結構可以包含其他結構的實例。然而,有些人認為,在使用嵌入式類型時,Go 中仍然存在脆弱的基類問題。
嵌入式類型將嵌入式類型的欄位和方法提升為包裝類型。雖然這提供了方便的訪問,但它消除了多態性。這意味著嵌入類型中定義的方法不能在包裝類型中重寫,並且嵌入類型進行的任何方法呼叫都將始終呼叫原始定義。
因此,存在脆弱基類問題在 Go 中以一種簡化的形式。對嵌入類型的方法或欄位的變更可能會影響包裝器類型,但前提是包裝器類型沒有定義自己的同名方法。
範例
考慮以下 Java 程式碼,其中基底類別 Counter 包含增量方法 inc() 和增量方法 incBy()。衍生類別 MyCounter 重寫 inc() 來呼叫 incBy(1)。
<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>
如果將基類中的incBy() 方法改為使用循環,則派生類MyCounter 將進入無限循環因為inc() 調用了incBy() ,而incBy() 又調用了inc () :
<code class="java">void incBy(int n) { for (; n > 0; n--) { inc(); } }</code>
在Go 中,同一範例不會出現此問題,因為Go 不支援嵌入類型中的重寫方法:
<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() 的方法。相反,它呼叫 Counter 類型中定義的原始 inc() 方法。
因此,由於嵌入類型缺乏多態性,脆弱的基類問題不是 Go 中的主要問題,這可以防止意外行為修改嵌入類型時。
以上是Go 的組合模型還會受到脆弱基類問題的困擾嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!