views:

369

answers:

3

Having something like this this :

public abstract class AAA
{
  protected abstract virtual string ToString()    // Error
  {
    // Base Stuff
  }
}

public abstract class BBB : AAA
{
  public override string ToString()
  {
    // Use base.ToString();
    // More Stuff
  }
}

I read another post (http://stackoverflow.com/questions/613327/abstract-method-in-a-virtual-class) witch was pretty like my question, but there is a little difference. I'd like AAA.ToString() to have a base behavior and force the derived class to override it.

I know I could do something like this (scroll down) but I was looking for a proper way.

public abstract class AAA
{
  public abstract string ToString();
  protected string ToString2()
  {
    // Base Stuff
  }
}

public class BBB : AAA
{
  public override string ToString()
  {
    // Use base.ToString2();
    // More Stuff
  }
}

I could also probably make a IAAA interface and build my BBB class like

public class BBB : AAA, IAAA { ... }

but don't look right to me.

+3  A: 

Your approach is essentially the proper way...

Edit:

Your "specification" is:

  1. Default behaviour
  2. Required override

Now, since you appear to want the "default behaviour" to always be executed, you need

public string ToString()
{
    // placeholder for some default behaviour

    string result = doToString();

    // placeholder for some more default behaviour

    return result;
}

protected abstract string doToString();

This only works if you know what the base class is doing in general, and want to provide the implementation for doToString() in the derived class. This is known as the Template Method design pattern.

However, if you are looking for a way to require the implementer of a derived class to call base.ToString() in its implementation of ToString(), then there's no way to do this. By allowing an override, you give the derived class control over its implementation.

You can document your recommendation to always call base.ToString(), but that's about it.

Using an interface defines the public contract for your class. This doesn't give you any additional benefit over the Template Method pattern, since you still need to derive from a base class to obtain the "default" implementation.

Do you have any details about what you are trying to provide in your base class as the "default behaviour"? Maybe that will help come to a better solution. Looking at the referenced question, this is essentially the same approach.

Nader Shirazie
Thanks, your edit made me realize something important! Even if I would find a miracle way to define ToString() in the base class and force the override in the derived class, there is simply no way I can force the override to use ToString()! I also found this post by an MVP about forcing override : http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/c25b6477-b990-4284-abaf-801ddf18207c .Thanks again sir.
Tipx
Glad to be of service. That post is by Marc Gravell... he's well known on SO too :)
Nader Shirazie
How does this compare with the OPs answer posted below?
Joe
+1 for the Method Template, a very useful but often overlooked pattern...
Thomas Levesque
@Joe: OPs answer below is the same as this
Nader Shirazie
@nader : Wow... I feel dumb. At first I didn't understood the solution completely (missed the "Protected" on the abstract method) ((I'm a lobbyist and I haven't seen much design patterns)) and I taught about that today. Now that I read this answer, I see that it's exactly the same!! Thanks again!
Tipx
@Tipx: Don't (feel dumb). If it took some working with it to 'get' it, then obviously the answer wasn't clear enough. Also, no better way to learn than to 'discover' it for yourself. Apologies if I came across as an ass.
Nader Shirazie
A: 

No, it isn't possible to turn a currently virtual function into an abstract function. The only way of enforcing this would be to create another function that's abstract, as you suggested. This is arguably a more appropriate approach (and I would agree with that).

Adam Robinson
A: 

I just found out what to do to get exactly the behavior I wanted :

public abstract class AAA
{
  protected abstract string ToStringSpecific();
  protected string ToString()
  {
    // Base Stuff
    ...
    // Use this.ToStringSpecific();
  }
}

public class BBB : AAA
{
  protected override string ToStringSpecific()
  {
    // Specific Stuff
  }
}
Tipx
I think you should've edited your original question...
Joe
I will indeed edit the question (and the title) so it might help someone find this topic, but I'll let my solution here. (If it shouldnt be done this way, there wouldn't be e "Anwser Your Question" button)
Tipx
I just re-read the second part of my comment and it "sounds" arrogant. I'm sorry for that, I didn't mean to be, and I can't edit the comment. I apology.
Tipx
@Tipx: Just curious, how is this different?
Nader Shirazie
@Tipx: No worries. Lots of people figure out the answer to their own questions and post it. In the end, we're all trying to get a definitive, useful answer for the question, and for all others that end up here with the same question...
Nader Shirazie
@nader: Read the comment I just added to your solution ;-)
Tipx