Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
185 views
Welcome To Ask or Share your Answers For Others

1 Answer

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...