我可以在另一个抽象派生类中从基类调用抽象方法吗?

时间:2017-09-13 10:31:46

标签: c# inheritance

假设我有这些课程:

abstract class A
{
    protected abstract void DoSomething();
    protected abstract void DoSomethingAnotherName();
}

abstract class SuperA : A
{
    private new void DoSomething()
    {
        base.DoSomething(); // <-- I can't do this.
        DoSomethingAnotherName(); // <-- But I can do this.
    }
}

sealed class FinalA : SuperA
{
    protected override void DoSomething() { ... }
    protected override void DoSomethingAnotherName() { ... }
}

我可以从另一个指定base关键字的抽象类调用基类抽象方法而不进行转换吗?我总是可以重命名private new DoSomething方法并删除base.部分,然后就可以了。但是,如果我希望这个方法像这样命名怎么办?

((dynamic)this).DoSomething() /* or */ ((FinalA)this).DoSomething()

也不起作用,因为在运行时这行在SuperA类中运行,它可以看到它自己的private DoSomething方法,所以有StackOverflowException

P.S。我真的不需要它,我只是注意到我的派生类中没有新的私有方法。我的代码与DoSomethingAnotherName方法类似。我很好奇是否可以运行此代码,如果实际上 在派生类中具有相同名称的方法。似乎这是不可能的。

如果有人想描述CLR的作用以及它是如何编译成IL的,以及为什么它根本不可能 - 我会很感激这一点,我就是这个主题。对我而言,虽然抽象类声明了抽象方法的“接口”,但我们无法从派生类型中调用它,这似乎很奇怪。我知道我们不能创建抽象类,因为它们尚未实现。但是当我从派生类中使用 base 时 - 很明显我运行的某个实例已经在某个地方构建了......

3 个答案:

答案 0 :(得分:1)

我错误地理解了base个关键字。这篇文章给出了详细的解释:https://stackoverflow.com/a/3733260/3270191

因此,无法从派生的抽象类调用基类抽象方法,该抽象类具有声明了相同名称的方法。您应该重命名该方法,以便在没有base字的情况下调用此方法。

答案 1 :(得分:0)

这样可行,但您必须将其从受保护更改为公共

abstract class A
{
    public abstract void DoSomething();
    protected abstract void DoSomethingAnotherName();
}

abstract class SuperA : A
{
    private new void DoSomething()
    {
        ((A)this).DoSomething();
    }
}

sealed class FinalA : SuperA
{
    public override void DoSomething() { }
    protected override void DoSomethingAnotherName() { }
}

答案 2 :(得分:0)

在抽象类中,所有抽象方法&#34;等待&#34;用于派生类中的具体实现。它们只是占位符,而不是更多。 A类中的DoSomething()也是如此,DoSomethingAnotherName()也是如此。

当您从派生的抽象类中的DoSomething()调用DoSomethingAnotherName()时,这没有问题,因为您仍然需要派生的非抽象类来实现DoSomethingAnotherName()。 SuperA.DoSomething()本身永远不会被调用。可以调用FinalA.DoSomething(),但FinalA必须实现DoSomethingAnotherName(),因此很清楚如果调用DoSomething()会发生什么。

当您调用base.DoSomething()时,您明确指定不能使用派生类的实现,因此必须使用抽象类A的实现。但是没有实现,只是一个占位符。这就是为什么不允许这样做的原因。