2

Let's say I have these classes:

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() { ... }
}

Can I call base class abstract method from another abstract class specifying base keyword without casting? I can always rename private new DoSomething method and remove base. part, then it works. But what if I want this method to be named like this?

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

also doesn't work since at runtime this line runs inside the SuperA class and it can see it's own private DoSomething method, so there's StackOverflowException.

P.S. I don't really need it, I just noticed that I have no new private methods in my derived class. My code is like with DoSomethingAnotherName method. I just got curious would it be possible to run this code if there actually was a method with the same name in a derived class. And it seems like it's not possible.

If anyone feels like describing what CLR does and how it is all compiled to IL and why it can't be possible at all - I'll appreciate this, I'm into the topic. To me it seems strange though that abstract class declares an "interface" of abstract methods and we can't call it from derived types. I understand that we can't create abstract classes since they are not implemented yet. But when I use base from derived class - that's obvious that I run an instance that already has been constructed somewhere...

Ivan Zyranau
  • 879
  • 2
  • 14
  • 33
  • abstract methods are just that - abstract. They're not defined, not implemented. So how can you call it? What would you expect to happen when you did? – ADyson Sep 13 '17 at 10:38
  • @ADyson you can call it if you do not write ```base.``` part. You are calling it from another abstract class. When you implement your final non-abstract class compiler makes sure you implement this method (it is implemented in FinalA). – Ivan Zyranau Sep 13 '17 at 10:40
  • 1
    You asked "Can I call base class abstract method specifying base keyword". The answer is no, because it's abstract. If you remove base then it'll generally call some _implementation_ of the abstract method in a derived class. – ADyson Sep 13 '17 at 10:42
  • @ADyson oh, so when you specify base keyword you are actually using the concrete base type and not some type that will be inferred at runtime? I guess that does answer my question :) So I guess there's no way then to call base method when names of base method and derived class method are the same. – Ivan Zyranau Sep 13 '17 at 10:43
  • Yes if you specify `base` it will try to call the version of the method in the base class directly. How could it possibly know what other type to infer? You told it precisely what to do. The point of `base` is to invoke the base method and not some override version. And in your example there isn't a real base DoSomething method. It's abstract. So you can't call it. If the method was overridable (and thus implemented), but not abstract, then you could call it. Again, it's not clear what you're expecting to happen when you call this abstract method anyway. – ADyson Sep 13 '17 at 10:48
  • It's nothing to do with your private method happening to have the same name as the base method (incidentally the fact it's private means it _doesn't_ serve as an implementation of the base method), it's everything to do with the base method being abstract. – ADyson Sep 13 '17 at 10:50
  • @ADyson if my methods would not have the same name, I could've just omitted the ```base.``` part and it would work just like with ```DoSomethingAnotherName``` method. I'm expecting ```new private DoSomething``` method to be able to call ```DoSomething()``` method implemented in ```FinalA``` class. – Ivan Zyranau Sep 13 '17 at 10:51
  • How could the class be able to call a method which is only implemented in a derived class? The class does not know its children. – Thern Sep 13 '17 at 10:53
  • the SuperA class knows nothing about the FinalA class. FinalA is derived from SuperA. So FinalA knows about SuperA but not the other way round. Parent classes don't depend on their children. You can write a parent class in one library, and some other code comes along, uses your library and inherits your class. This can happen 1000 times, in different projects. It's completely impossible for the parent class to know about the children. This is an inherent feature of OO design. Perhaps if you explain what you actually want as your end goal here we can help you with how to do something that works – ADyson Sep 13 '17 at 10:53
  • To be 100% clear, when you call `base` it refers to `A`. which is the base (parent) class of `SuperA`. It does not, and cannot, refer to `FinalA`. – ADyson Sep 13 '17 at 10:56
  • I still don't understand completely why can't you call abstract member using ```base``` keyword. You are calling it from inside the derived type, so you are sure that the class has been created somewhere (hence all abstract methods are properly implemented). See my updated question. – Ivan Zyranau Sep 13 '17 at 11:12
  • @EwanCoder I think you're right that it could meaningfully be added in to the spec, but this is probably such a corner case it's not really worth it. If really desperate you could change the name, or use the answer I suggested. – Yair Halberstadt Sep 13 '17 at 11:20
  • Actually I remembered that Jeffrey Richter wrote that when you call base methods it wouldn't read virtual methods table and will call directly type's method. That's obvious or else there would be infinite loops in virtual methods calling base methods leading to StackOverflowException. This kind of sums up the question: this is not possible to call abstract base class method with the same name. – Ivan Zyranau Sep 13 '17 at 11:31

3 Answers3

1

I understood base keyword incorrectly. Detailed explanations are given in this post: https://stackoverflow.com/a/3733260/3270191

So there's no way to call base class abstract method from derived abstract class that has method with the same name declared. You should rename the method in order to call this method without the base word.

Ivan Zyranau
  • 879
  • 2
  • 14
  • 33
0

This would work, but you'd have to change it from protected to public

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() { }
}
Yair Halberstadt
  • 5,733
  • 28
  • 60
0

In an abstract class, all abstract methods "wait" for a concrete implementation in a derived class. They are just placeholders, not more. So is DoSomething() in class A, and so is DoSomethingAnotherName() as well.

When you call DoSomethingAnotherName() from DoSomething() in a derived abstract class, this is no problem because you still need a derived non-abstract class to implement DoSomethingAnotherName(). SuperA.DoSomething() itself will never be called. FinalA.DoSomething() can be called, but FinalA must implement DoSomethingAnotherName(), so it is clear what happens if DoSomething() is called.

When you call base.DoSomething(), you explicitly specify that no implementation of the derived class may be used, so the implementation of the abstract class A must be used. But there is no implementation, just a placeholder. That is why this is not allowed.

Thern
  • 1,017
  • 8
  • 17