tags:

views:

196

answers:

5

Lets say i have the following c# classes:

abstract class a
{
    protected abstract void SomeMethod();
}

abstract class b : a
{
    protected abstract override void SomeMethod();
}

class c : b
{
    protected override void SomeMethod()
    {

    }
}

Is there actually any point in overriding the method in b when it could just as easily be writen as:

abstract class b : a
{
}

What would be the "prefered" way of writting b? And if there is no point overriding an abstract method or property why is it allowed?

+5  A: 

One reason you might want to allow it: it shows intent. It explains that yes, you know this method is abstract in the base class. I know that, and I still want it to be abstract here.

That way, if the base class removes the method, your abstract class will fail to compile, rather than only the concrete class (which may not even be in your code).

That said, it's not a particularly important reason... I'd normally leave it out.

Jon Skeet
I'm not sure I understand... what is the benefit of adding one more point of compilational failure? Also, if your base class adds yet another abstract method and you don't refactor your derivatives you won't get this result consistently.
LBushkin
@LBushkin: True, you won't spot additions... but adding another point of failure might be useful if you wouldn't otherwise have *any* (bearing in mind that you may not have the concrete class anywhere in your codebase). I'm not saying it'll come up often...
Jon Skeet
Any description in an inheritance tree (decriptive code, or *meaningful* comments) are appreciated. Inheritance makes the interaction of the base and derived classes a bit of a mystery--especially if (a) the base class is anything other than a simple, well designed and focused object (b) if the maintainer did not write both the base and the derived class. Inheritence is great, but can be greatly abused to make magically cruft-riddled code
STW
A: 

You should not need to override SomeMethod() in b. An abstract class declares that there can be undefined/abstract methods in it. When you extend one abstract class with another, it implicitly inherits any abstract methods from the parent.

geofflane
Of course, doesn't this mean that the class becomes abstract itself and cannot be instantiated without a child class that DOES implement the method?
Kelly French
Correct, the B class would be abstract as well. C# requires you explicitly declare it abstract as well and will give you a compiler error if you don't.
geofflane
+2  A: 

Have a look at this blog. Sometimes combining both is useful:

"Good language design usually results in a few well defined simple primitives that can be combined together in intuitive and intelligent ways. In contrast, poor language design usually results in many bloated constructs that don't play well together.

The "abstract" and "override" keywords in C# are a great example of this. They both have simple definitions, but they can be combined to express a more complex concept too.

Let's say you have a class hierarchy: C derives from B, and B derives from A. A has an abstract method Foo() and Goo(). Here are 2 scenarios where "abstract override" would come up. 1) Let's say B only wants to implement Goo(), and let C implement Foo(). B can mark Foo() as "abstract override". This clearly advertises that B recognizes Foo() is declared in the base class A, yet it expects another derived class to implement it.

2) Let's say B wants to force a C to reimplement Foo() instead of using A's definition of Foo(). B marks Foo() as both override (which means B recognizes Foo() is declared in the base class) and abstract (which means B forces derived class C to provide an implementation; regardless that A already provided an implementation). This came up in one of my recent blog entries here. In that example, A=TextReader, Foo=ReadLine, B= a helper class, C=some class that wants to implement ReadLine() instead of Read(). Now TextReader already has a default implementation of ReadLine() based on Read(), but we want to go the other way around. We want an implementation of Read() based off a derived classes implementation of ReadLine(). Thus B provides an implementation of Read() that consumes ReadLine(), and then marks ReadLine() as "abstract override" to force C to redefine ReadLine() instead of picking up the one from TextReader.

In summary, "abstract override" is cool not because it's yet one more language feature to express some complex corner case; it's cool because it's not one more language feature. The neat part is that you don't really need to think about any of this. You just use the individual basic concepts naturally, and the complicated stuff comes together automatically."

This is my example code for scenario 1:

public abstract class A
{
    public abstract void Foo();
    public abstract void Goo();
}

public abstract class B : A
{

    public abstract override void Foo();

    public override void Goo()
    {
        Console.WriteLine("Only wanted to implement goo");
    }
}

public class C : B
{

    public override void Foo()
    {
        Console.WriteLine("Only wanted to implement foo");
    }
}

And my sample code for scenario 2:

public abstract class A
{
    public virtual void Foo()
    {
        Console.WriteLine("A's Foo");
    }
    public abstract void Goo();
}

public abstract class B : A
{

    public abstract override void Foo();

    public override void Goo()
    {
        Console.WriteLine("Only wanted to implement goo");
    }
}

public class C : B
{

    public override void Foo()
    {
        Console.WriteLine("Forced to implement foo");
    }
}

In your question the code is not that useful, but that doesn't mean that abstract and override combined is not useful.

RichardOD
+2  A: 

I normally don't re-declare abstract methods when I don't actually intend to supply an implementation - for several reasons:

  • I doesn't change the semantics of your code.
  • It adds one more thing to refactor if the base class changes.
  • It leads to inconsistency of new abstract methods are added to the base class and you don't add them to intermediate classes.
  • It's quite painful to do so in a class hierarchy with more than a few levels.
  • It clutters your code with declaration that add little value.
LBushkin
+2  A: 

Additional to the already said:

override could also be used to declare attributes that are not defined in the base class. If still not having an implementation, it will be an abstract override.

abstract class b : a
{
  [SomeAttribute]  
  protected abstract override void SomeMethod();
}
Stefan Steinegger
That's a good point. As a side issue if DataMember is System.Runtime.Serialization.DataMemberAttribute your code won't compile. I think people get the idea though.
RichardOD
Ok, just took the first attribute that came to my mind :-) fixed it.
Stefan Steinegger