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中文网其他相关文章!