在基类内强制调用基类虚方法

3

别误会我的意思:我不想像之前已经问过1000次那样强制调用覆盖方法中的基类方法 :)

我想知道是否有一种方法可以在基类内部强制调用基类实现的方法。

例如:

using System;

public class Program
{
    public static void Main()
    {
        var c = new SubClass();
        c.CallInfo();
    }

    internal class BaseClass {
        protected virtual void Info(){
            Console.WriteLine("BaseClass");
        }

        internal virtual void CallInfo() {
            this.Info();
        }
    }

    internal class SubClass : BaseClass {
        protected override void Info() {
            Console.WriteLine("SubClass");
        }

        internal override void CallInfo() {
            base.CallInfo();
        }
    }
}

显然输出是SubClass。有没有办法强制BaseClassCallInfo方法调用它自己的Info方法,以便输出为BaseClass


你可以为基类创建一个构造函数,在其创建期间调用自身的Info()。但是,你能否澄清一下你真正想要实现什么?预期输出是什么?你想同时看到Subclass和BaseClass的WriteLine()内容吗?对于先完成BaseClass,然后再完成Subclass,这一点重要吗? - DRapp
不,正如粗体字注释所澄清的那样:我不想强制从子类调用任何基础方法。只是强制从其他基础方法中调用虚拟基础方法。 - infotoni91
2个回答

4
通过将您的Info()方法标记为virtual,您明确要求发生此类型的继承行为。
如果您想确保基类中的方法调用不被覆盖,您需要使用非虚方法,例如:
internal class BaseClass {
    protected virtual void Info(){
        this.FinalInfo();
    }

    protected void FinalInfo() {
        Console.WriteLine("BaseClass");
    }

    internal virtual void CallInfo() {
        this.FinalInfo();
    }
}

感谢您澄清虚拟关键字的含义。这个“变通方法”对我来说很明显,但我想知道是否有其他方法可以实现我想要的功能。 - infotoni91
@infotoni91,为什么你要寻找“另一种方法”?这种方法有什么不好的地方让你感到不舒服/犹豫不决?回答中所展示的方法有何问题? - user2819245
我必须将许多这样的方法污染到基类中。有一些方法我最终会以某种方式进行保护,以达到确定性。 - infotoni91
@infotoni91,如果你需要为许多方法做这件事,那么你似乎在类型/类设计上存在缺陷。可能值得重新思考类型层次结构的设计和结构。 - user2819245
这是一个庞大的项目,有150万行代码。对于一个非常特定的情况,我通过EntityFramework注入SubClass来替换和扩展BaseClass。实际设计是稳定和一致的,但我现在正在计划和设计我的模块,还有一些不一致的地方需要解决 :) - infotoni91

1
不,你不能这样做。虚方法的目的是派生类可以重写实现,并且即使从基类调用它也会使用实现。
如果这会引起问题,那么您想要运行的方法就不应该是虚方法。
这将起作用,虽然它不像虚方法那样强制子类实现,但它允许您覆盖它。
public class Program
{
    public static void Main()
    {
        var c = new SubClass();
        c.CallInfo();
    }

    internal class BaseClass
    {
        protected void Info()
        {
            Console.WriteLine("BaseClass");
        }

        internal virtual void CallInfo()
        {
            this.Info();
        }
    }

    internal class SubClass : BaseClass
    {  
        protected new void Info()
        {
            Console.WriteLine("SubClass");
        }

        internal override void CallInfo()
        {
            base.CallInfo();
        }
    }
}

成员隐藏并不等同于覆盖(虚拟)方法。因此,你的回答并没有真正匹配问题的上下文。 - user2819245
顺便提一下,注意Keiwan的答案,它在不改变Info方法调用解析的“行为”情况下实现了所需的行为。 - user2819245
谢谢,但是现在编辑后的代码不符合我的原始逻辑,因为没有可调用的成员Info,可以提供“SubClass”。 - infotoni91
2
@elgonzo 不,仅仅缺少一个方法而已 ;) - infotoni91
哦,抱歉,我没有注意到缺少的方法。我的错,我道歉。但是随着最新的编辑,我们又回到了成员隐藏的情况(这是我在第一条评论中指出的),不同之处在于这次省略了 new 关键字(从而产生编译器警告)。无论如何,我现在签退了。我不想无休止地闲扯下去...;-) - user2819245
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接