3
interface ICanvasTool
{
    void Motion(Point newLocation);
    void Tick();
}

abstract class CanvasTool_BaseDraw : ICanvasTool
{
    protected abstract void PaintAt(Point location);

    public override void Motion(Point newLocation)
    {
        // implementation
    }
}

class CanvasTool_Spray : CanvasTool_BaseDraw
{
    protected abstract void PaintAt(Point location)
    {
        // implementation
    }

    public override void Tick()
    {
        // implementation
    }
}

This doesn't compile. I could add an abstract method "Tick_Implementation" to CanvasTool_BaseDraw, then implement ICanvasTool.Tick in CanvasTool_BaseDraw with a one-liner that just calls Tick_Implementation. Is this the recommended workaround?

Stefan Monov
  • 11,332
  • 10
  • 63
  • 120
  • I am not sure what you mean by "workaround" as you are using an interface. An interface is a contract, and therefore any type that implements the interface MUST adhere to that contract. This enforcement by the compiler is done so callers of your class can know for a fact that any type implementing ICanvasTool has those two methods on it. – Josh Apr 13 '10 at 12:38
  • Yes, I *want* the compiler to enforce that any nonabstract descendant of the interface implements all of it. I just don't want this to be the case for *abstract* descendants. – Stefan Monov Apr 13 '10 at 12:41
  • BTW, Java does it my way. See http://stackoverflow.com/questions/197893 – Stefan Monov Apr 13 '10 at 12:43

4 Answers4

6

The way to do this is to add an abstract void Tick() method to CanvasTool_BaseDraw and override it in CanvasTool_Spray.

Not every programming language does it this way. In Java you do not have to add an abstract method for every method in the interface(s) you implement. In that case your code would compile.

Ronald Wildenberg
  • 31,634
  • 14
  • 90
  • 133
4

You have a few things mixed up..

Motion should be virtual in your base class so that it may be overridden in child classes. Your child class needs to make PaintAt override instead of abstract. The base class needs to implement Tick as an abstract method.

interface ICanvasTool
{
    void Motion(Point newLocation);
    void Tick();
}

abstract class CanvasTool_BaseDraw : ICanvasTool
{
    protected abstract void PaintAt(Point location);

    public virtual void Motion(Point newLocation)
    {
        // implementation
    }

    public abstract void Tick();
}

class CanvasTool_Spray : CanvasTool_BaseDraw
{
    protected override void PaintAt(Point location)
    {
        // implementation
    }

    public override void Tick()
    {
        // implementation
    }
}
Krisc
  • 1,357
  • 2
  • 14
  • 22
  • Yeah, the first two mistakes were the result of impatiently rushing a code-example for SO. And your solution is correct. Thanks. – Stefan Monov Apr 13 '10 at 12:39
  • Er, hold on. Why does Motion need to be virtual in CanvasTool_BaseDraw? I don't really need to allow subclasses to override it. – Stefan Monov Apr 13 '10 at 12:49
  • I apologize. It doesn't _have_ to be. I just assumed that you wanted it to be overridable since it was a base class. However, using 'override' there is illegal since you are implementing an interface, not inheriting an abstract class or class with a virtual method. – Krisc Apr 13 '10 at 13:14
1

An alternative is don't list the interface in the base classes declaration. Each derived class must list ICanvasTool in its declaration if it wants to be implementing the interface and then it is solely responsible for implementing the rest of the interface. One drawback I can see is you can't explicitly implement the interface methods in the base class (ie no ICanvasTool:Motion), but otherwise this is a fairly low overhead version.

public interface ICanvasTool
{
    void Motion(Point newLocation);
    void Tick();
}

public abstract class CanvasTool_BaseDraw
{
    public void Motion(Point newLocation)
    {
        //some implementation
    }
}

public class CanvasTool_Spray : CanvasTool_BaseDraw, ICanvasTool
{
    public void Tick()
    {
        //some implementation
    }
}

Note: I left out PaintAt because it wasn't necessary for the example.

numerek
  • 177
  • 1
  • 7
0

As was stated before, an interface is a contract and therefore all of it needs to be implemented. If a a consumer tried to call something that is defined in the interface but not implemented in the concrete class the application would crash.