user206334
user206334

Reputation: 882

Why does a public non-virtual member of a superclass interfering with overriding in a subclass

What is a design rationale behind this:

OK:

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    private new void DoWork() { Console.WriteLine("B"); } //private works
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

WRONG:

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    public new void DoWork() { Console.WriteLine("B"); } //public doesn't
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

Why does non-virtual method interfere with overriding virtual method anyway?

1st case: compiler checks that the method is private (new) so it allows class C.DoWork() to override class A.DoWork() (does not mix virtual and not-virtual (B.DoWork()) methods).

2nd case: compiler sees that public (new) void is declared and it arbitrarily(?) disrupts overriding in class C.

Now, if I wanted to declare new virtual DoWork() I could have done it, if I wanted to disallow overriding, I could have used sealed specifier. But in this case I wrote public void DoWork() as declaring normal non-virtual method and I do not expect it participating in virtual inheritance chain as in the private case. In 2nd example I expect:

A ac = new C();
ac.DoWork();

to print C as in the private case.

Upvotes: 1

Views: 110

Answers (3)

mihirj
mihirj

Reputation: 1219

In below code

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    private new void DoWork() { Console.WriteLine("B"); } //private works
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

you are telling the compiler that DoWork() method in B class is a new version of class A's DoWork() method. However, it allows you to override DoWork in C due to the fact that you have declared DoWork's new version as private in B which makes the compiler assume that that method is not exposed to the outside world.

However, in this,

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    public new void DoWork() { Console.WriteLine("B"); } //public
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); }
}

You are telling the compiler to override new version of method DoWork(), which is a bit wrong from compiler's point of view as it cannot override a non abstract/virtual/overriden method as per the rules set while designing the language.

That is why, I think, your code gives error in one case and not the other.

Upvotes: 0

Ilya Ivanov
Ilya Ivanov

Reputation: 23626

In first example your C class ovverides A's DoWork (B had DoWork, which is private and not visible to subclasses). In second example you hide DoWork by non-virtual function and compiler complains, that you are trying to override non-virtual function. Solution is to expose families of virtual functions. By new virtual you can create separations between these families.

public class B : A
{
    public new virtual void DoWork() { Console.WriteLine("B"); } //private works
}

This code then

A a = new C();
a.DoWork();

prints A

B b = new C();
b.DoWork();

prints C

You can read in more detail how new virtual is used in Knowing When to Use Override and New Keywords. new keyword without virtual has a different semantics from new virtual, you can read more about it at new keyword in method signature.

Upvotes: 0

Tigran
Tigran

Reputation: 62256

Because in first case you're overriding an A class function and not B one

public class A
{
    public virtual void DoWork() { Console.WriteLine("A"); }
}
public class B : A
{
    private new void DoWork() { Console.WriteLine("B"); } //private works
}
public class C : B
{
    public override void DoWork() { Console.WriteLine("C"); } //OVERRIDES A.DoWork()
}

You can not override non virtual/abstract methods of the base class.

Upvotes: 0

Related Questions