Let's say that I have an abstract base class something simple like
abstract class Item : IDisplayable { public int Id { get; set; } public string Name { get; set; } public abstract void Print(); }
and I have a class that inherits from that like
class Chair: Item { public int NumberOfLegs {get;set;} public void Print() { Console.WriteLine("Here is a simple interface implementation"); } } interface IDisplayable { void Print(); }
the child class does not explicitly say that it also implements the Interface, and yet it will do so through simple inheritance. If we explicitly add the Interface to the child classes the program will run the same (at least as far as I can tell in my simple examples). Would explicitly implementing the interface be a good or bad idea, or is it strictly a matter of preference?
A class implements an interface, thereby inheriting the abstract methods of the interface. Along with abstract methods, an interface may also contain constants, default methods, static methods, and nested types. Method bodies exist only for default methods and static methods.
Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.
Abstract Class. An abstract class permits you to make functionality that subclasses can implement or override whereas an interface only permits you to state functionality but not to implement it. A class can extend only one abstract class while a class can implement multiple interfaces.
Consider using interfaces if any of these statements apply to your situation: It is total abstraction, All methods declared within an interface must be implemented by the class(es) that implements this interface. A class can implement more than one interface.
If we explicitly add the Interface to the child classes the program will run the same (at least as far as I can tell in my simple examples).
The program will not necessarily run the same; your examples are insufficient to illustrate the difference.
Would explicitly implementing the interface be a good or bad idea, or is it strictly a matter of preference?
It is a bad idea unless you intend to ensure interface re-implementation semantics.
Let me illustrate briefly. What does this program do?
using System; interface IFoo { void Bar(); void Baz(); } class Alpha : IFoo { void IFoo.Bar() { Console.WriteLine("Alpha.Bar"); } void IFoo.Baz() { Console.WriteLine("Alpha.Baz"); } } class Bravo : Alpha { public void Baz() { Console.WriteLine("Bravo.Baz"); } } class CharlieOne : Bravo { public void Bar() { Console.WriteLine("CharlieOne.Bar"); } } class CharlieTwo : Bravo, IFoo { public void Bar() { Console.WriteLine("CharlieTwo.Bar"); } } class Program { static void Main() { IFoo foo = new Alpha(); foo.Bar(); foo.Baz(); foo = new Bravo(); foo.Bar(); foo.Baz(); foo = new CharlieOne(); foo.Bar(); foo.Baz(); foo = new CharlieTwo(); foo.Bar(); foo.Baz(); } }
Before you read on, seriously: try to predict the output of this program.
Now actually run it. Did you get the output you expected? Where was your intuition wrong?
Do you see the difference between CharlieOne
and CharlieTwo
now? Re-implementing IFoo
in CharlieTwo
can cause the interface binding to pick up Bravo.Baz
even though Bravo
does not re-implement IFoo
!
And on the other hand: if you expected Bravo.Baz
to be assigned to the interface slot just because it exists, then you see how failing to re-implement an interface causes the code to be incorrect. For Bravo.Baz
to replace Alpha.IFoo.Baz
, Bravo
must re-implement IFoo
.
The takeaway here is: when you re-implement an interface, all the interface bindings are recomputed from scratch. This can cause semantic changes in your program, so only re-implement an interface when you mean to do so.
This also illustrates yet another form of the brittle base class failure. Suppose Bravo
does not have method Baz
when you write Charlie
. If you write Charlie
to re-implement IFoo
then the author of Bravo
adding Baz
afterwards -- perhaps the authors of Bravo
are on a different team at your company -- changes the interface bindings within Charlie
even if that is not what the authors of Bravo
intended.
For more information, see my article on the subject:
http://blogs.msdn.com/b/ericlippert/archive/2011/12/08/so-many-interfaces-part-two.aspx
Since Item
inherits from IDisplayable
, anything that derives from Item
must also implement IDisplayable
. So explicitly adding IDisplayable
to those classes is redundant.
EDIT: @EricLippert makes an excellent point below about the effect of re-implementing interfaces. I'm leaving this answer to preserve the discussion in the comments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With