Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract base classes that implement an interface

Tags:

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?

like image 916
wootscootinboogie Avatar asked Jun 24 '13 14:06

wootscootinboogie


People also ask

Which class is used to implement an interface?

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.

What are interfaces abstract classes?

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.

Is an abstract base class an interface?

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.

How many interfaces can an abstract class implement?

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.


2 Answers

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

like image 87
Eric Lippert Avatar answered Oct 22 '22 17:10

Eric Lippert


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.

like image 20
neontapir Avatar answered Oct 22 '22 18:10

neontapir