当前位置: 首页 > 面试题库 >

Go中是否存在脆弱的基类问题?

朱保赫
2023-03-14
问题内容

尽管使用了组合而不是继承?

如果是这样,在语言级别上有什么解决方案吗?


问题答案:

正如VonC所写,但我想指出一点。

所述脆弱的基类问题通常归咎于虚拟方法(
方法动态调度 -这意味着如果方法可重写的,其具有的实际实现在这样的重写方法只能在运行时被决定的情况下被调用)。

为什么这是个问题?您有一个类,向其中添加了一些方法,如果进行了MethodA()调用MethodB(),则不能保证MethodB()您所编写的将被调用,并且不能保证子类的其他方法可以覆盖您的MethodB()

在Go中有嵌入,但是没有多态性。如果将类型嵌入结构中,则嵌入类型的所有方法都将得到
提升,
并且将位于包装器结构类型的方法集中。但是您不能“替代”升级的方法。当然,您可以添加具有相同名称的自己的方法,然后在包装结构上以该名称调用方法将调用您的方法,但是如果从嵌入式类型调用此方法,则不会分派给您的方法,它将仍将调用已定义为嵌入式类型的“原始”方法。

因此,因此,我要说的是,脆弱的基类问题在Go语言中仅以相当缓解的形式存在。

演示Java中的问题

让我们来看一个例子。首先在Java中,因为Java遭受这种问题的困扰。让我们创建一个简单的Counter类和一个MyCounter子类:

class Counter {
    int value;

    void inc() {
        value++;
    }

    void incBy(int n) {
        value += n;
    }
}

class MyCounter extends Counter {
    void inc() {
        incBy(1);
    }
}

实例化和使用MyCounter

MyCounter m = new MyCounter();
m.inc();
System.out.println(m.value);
m.incBy(2);
System.out.println(m.value);

输出是预期的:

1
3

到目前为止,一切都很好。现在,如果将基类Counter.incBy()更改为:

void incBy(int n) {
    for (; n > 0; n--) {
        inc();
    }
}

基础类Counter仍然保持完美无缺且可操作。但是MyCounter变得不正常了:MyCounter.inc()调用Counter.incBy()inc()由于动态调度,它会调用MyCounter.inc()…是…无限循环。堆栈溢出错误。

演示Go中 缺少 的问题

现在让我们看一下相同的示例,这次是用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)
}

测试它:

m := &MyCounter{}
m.Inc()
fmt.Println(m.value)
m.IncBy(2)
fmt.Println(m.value)

输出是预期的(在Go Playground上尝试):

1
3

现在,让Counter.Inc() 我们以与Java示例相同的方式进行更改:

func (c *Counter) IncBy(n int) {
    for ; n > 0; n-- {
        c.Inc()
    }
}

它运行完美,输出是相同的。在Go Playground上尝试一下。

这里发生的是MyCounter.Inc()will call
Counter.IncBy(),它将调用Inc(),但这Inc()将是Counter.Inc(),因此这里没有无限循环。Counter甚至都不知道MyCounter,它没有对embedder
MyCounter值的任何引用。



 类似资料:
  • 问题内容: Java中的脆弱基类问题是什么? 问题答案: 脆弱的基类是继承的普遍问题,它适用于Java和任何其他支持继承的语言。 简而言之,基类是您要从其继承的类,通常将其称为易碎类,因为对此类所做的更改可能会在从其继承的类中产生意外结果。 缓解这种情况的方法很少;但是没有一种简单的方法可以在仍然使用继承的情况下完全避免使用它。您可以通过像Java中一样标记类声明来防止其他类从类继承。 避免这些问

  • 问题内容: 我有一个Swift类,需要存储自己的方法表。不幸的是,这导致了一个引用周期,因为它的表通过其存储的方法保留了对它的引用。 以下示例泄漏代码: 到目前为止,我发现的唯一解决方案是改为执行此操作: 这很丑陋,而且容易出错。还有更好的主意吗?是否有一些使函数引用本身变弱的技巧?即使类型的数组或什么?据我所知,我什至无法在上述丑陋的封闭包装上构建作为语法糖的便捷功能。 问题答案: 您当然可以为

  • 我知道C中的未对齐访问是什么,它可能会导致某些处理器UB。 我想知道这样写在NASM汇编上的代码中是否存在同样的问题:

  • 问题内容: Go的标准库没有专门用于检查文件是否存在的函数(如Python的)。什么是 惯用的 方式做到这一点? 问题答案: 要检查文件是否不存在,等同于Python的文件: 要检查文件是否存在,等效于Python的文件: 编辑:根据最近的评论

  • Go的标准库没有专门用于检查文件是否存在的功能(如Python的)。

  • 问题内容: Java的8提供专业化的,和:,和分别。但是,我在文档中找不到与之等效的文档。 Java 8是否提供类? 问题答案: 不,它不存在。实际上,它没有明确实现,以便不会为每种原始类型的吨类添加混乱的Stream API。 引用一个邮件从布赖恩戈茨在OpenJDK的邮件列表: 简短的回答:不。 对于几乎从未使用过的这些表单,每个JDK占用100K +的空间都不值得。如果我们添加了这些,那么有