Using interfaces on abstract classes in C#

30,199

Solution 1

You're running into the issue because you used explicit interface implementation (EII). When a member is explicitly implemented, it can't be accessed through a class instance -- only through an instance of the interface. In your example, that's why you can't call DoCool() unless you cast your instance to IDoesCoolThings.

The solution is to make DoCool() public and remove the explicit interface implementation:

public abstract class AbstractWidget : IDoesCoolThings
{
    public void DoCool()      // DoCool() is part of the abstract class implementation.
    {
        Console.Write("I did something cool.");
    }
}

// ...

var rw = new RealWidget();
rw.DoCool();                  // Works!

In general, you use EII in two cases:

  • You have a class that must implement two interfaces, each of which contains a member that has an identical name/signature to another member in the other interface.
  • You want to force clients not to depend on the implementation details of your class, but rather on the interface that's being implemented by your class. (This is considered a good practice by some.)

Solution 2

Change your declaration to:

public abstract class AbstractWidget : IDoesCoolThings 
{
    public void DoCool()
    { 
        Console.Write("I did something cool."); 
    }
}

Solution 3

The way you implement the interface is explicit implement void IDoesCoolThings.DoCool(), if you choose implicit implement interface.

public abstract class AbstractWidget : IDoesCoolThings
{
    public void DoCool()
    {
        Console.Write("I did something cool.");
    }
}

Then it will work.

Read this :

C# Interfaces. Implicit implementation versus Explicit implementation

Solution 4

You should do it this way:

public interface IDoesCoolThings 
{
   void DoCool();
}

public abstract class AbstractWidget 
{
   public void DoCool()
   {
      Console.WriteLine("I did something cool.");
   }
}

public class Widget : AbstractWidget, IDoesCoolThings 
{
}

Usage:

var widget = new Widget();
widget.DoCool();
Share:
30,199
JubJub
Author by

JubJub

Updated on April 16, 2020

Comments

  • JubJub
    JubJub about 4 years

    I'm learning C# coming from C++ and have run into a wall.

    I have an abstract class AbstractWidget, an interface IDoesCoolThings, and a class which derives from AbstractWidget called RealWidget:

    public interface IDoesCoolThings
    {
        void DoCool();
    }
    
    public abstract class AbstractWidget : IDoesCoolThings
    {
        void IDoesCoolThings.DoCool()
        {
            Console.Write("I did something cool.");
        }
    }
    
    public class RealWidget : AbstractWidget
    {
    
    }
    

    When I instantiate a RealWidget object and call DoCool() on it, the compiler gives me an error saying

    'RealWidget' does not contain a definition for 'DoCool'

    I can cast RealWidget object to an IDoesCoolThings and then the call will work, but that seems unnecessary and I also lose polymorphism (AbstractWidget.DoCool() will always be called even if i define RealWidget.DoCool()).

    I imagine the solution is simple, but I've tried a variety of things and for the life of me can't figure this one out.

    • Anton Tykhyy
      Anton Tykhyy about 15 years
      To have polymorphism in widgets' DoCool(), you'd need to declare the AbstractWidget's one virtual.
    • JubJub
      JubJub about 15 years
      Erg. I'd read somewhere that virtual was implied for interface methods.
  • JubJub
    JubJub about 15 years
    God, I thought I'd tried that. Thanks! I seemed to have missed this key line in my reference book: "a method defined by using explicit interface implementation cannot be declared as virtual, whereas omitting the interface name allows this behavior."
  • JubJub
    JubJub about 15 years
    I was confused that simply making the method public in the abstract class didn't fix the problem, plus the examples I read didn't define methods as public or private, so I came to believe interface methods are implicitly public and virtual. Overall, an embarrassing question :). Thanks though!
  • hitec
    hitec about 15 years
    Thanks for adding the link to the SO question on implicit and explicit implementation !
  • supercat
    supercat about 11 years
    Explicit interface implementation can also be good if it's possible that a derived class' override of a member may wish to return a type which is derived from the base class' implementation. For example, both CarFactory and ICarFactory may have MakeCar() method which returns Car, but FordCarFactory may want to have a MakeCar() method return a FordCar. That could often be best handled by having a protected virtual DoMakeCar method that returns Car, and having both ICarFactory.MakeCar and a non-virtual CarFactory.MakeCar method chain to that.