Using interfaces on abstract classes in C#
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();
JubJub
Updated on April 16, 2020Comments
-
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 about 15 yearsTo have polymorphism in widgets' DoCool(), you'd need to declare the AbstractWidget's one virtual.
-
JubJub about 15 yearsErg. I'd read somewhere that virtual was implied for interface methods.
-
-
JubJub about 15 yearsGod, 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 about 15 yearsI 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 about 15 yearsThanks for adding the link to the SO question on implicit and explicit implementation !
-
supercat about 11 yearsExplicit 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
andICarFactory
may haveMakeCar()
method which returnsCar
, butFordCarFactory
may want to have aMakeCar()
method return aFordCar
. That could often be best handled by having aprotected
virtualDoMakeCar
method that returnsCar
, and having bothICarFactory.MakeCar
and a non-virtualCarFactory.MakeCar
method chain to that.