【问题标题】:Calling an overridden method from base constructor从基本构造函数调用重写的方法
【发布时间】:2011-01-01 19:44:16
【问题描述】:

我们有一个这样的类:

class LogAnalyzer
    {
        protected IExtensionManager manager;

        public  LogAnalyzer()
        {
            GetManager();
        }

        protected virtual void GetManager()
        {
            manager = new FileExtensionManager();
        }
    }

我们派生出另一个这样的类:

class TestableLogAnalyzer:LogAnalyzer
    {
        protected override void GetManager()
        {
            this.manager = new StubExtensionManager();
        }
    }

当我们实例化子类时,OOP 规则中应该发生什么?虚拟或被覆盖的方法是否被调用,为什么?我在 C# 中对其进行了测试,并且覆盖的方法有效,但我怀疑它在解释语言中可能是相反的。这是真的吗?

【问题讨论】:

  • 一篇非常受欢迎的文章,从 C++ 的角度回答了这个特定问题:artima.com/cppsource/nevercall.html
  • @John Saunders:我想知道是否所有 OO 语言都以同样的方式做这件事。阅读 AraK 发布的文章后,我发现情况并非如此。

标签: oop language-agnostic inheritance overriding virtual-functions


【解决方案1】:

为此提供与语言无关的答案并不简单,因为“发生的情况”取决于语言本身。例如,在 Java 中,会调用被覆盖的(虚拟)方法,但这可能会出现问题,因此不推荐使用。

您需要查阅您感兴趣的文档或语言规范,然后四处阅读以查看是否有人发表了关于您为什么应该或不应该这样做的意见,以及可能出现的问题,例如 Scott AraK 在他/她的评论中链接到的 Meyers 文章。

【讨论】:

    【解决方案2】:

    由于它与语言无关,我将使用 C++ 作为基础,并希望可以推断出建议。

    LogAnalyser 的构造函数在 TestableAnalyser 的构造函数之前调用。这意味着在其工作期间 TestableAnalyser 尚未构造,因此调用虚拟方法可能很危险(它们可能使用未初始化的数据)。

    在您的情况下,派生类希望影响其基类的初始化。覆盖虚拟方法并不是唯一的方法。您可以再创建一个接受管理器的构造函数,派生类将传递“new StubExtensionManager();”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 2017-02-04
      • 2010-09-25
      • 2012-04-09
      • 2015-08-29
      • 2011-03-05
      • 2014-02-04
      相关资源
      最近更新 更多