views:

241

answers:

7

In the C# example of polymorphism, there is a Cat class which inherits a class called AnimalBase and an interface called IAnimal.

The link in question is: http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming

My question is, why is both a base class and an interface used? Why not one or the other? I was of the school of thought that only an abstract class would be required for implementing polymorphism.

Thanks

+7  A: 

Base Classes are used when you want to reuse BEHAVIOR

Interfaces are used when you want to control how the class INTERACTS with other objects. It defines the interaction in a precis manner.

In my experience the amount of times you want to control how classes interact dwarfs the times when you want to reuse behavior.

RS Conley
Although I understand yr point, I would never word it this way. Interfaces enforce Behavior. base classes are for reuse of "Implementation"... that's why naming conventions for interfaces suggest using "I[Verb/Adverb]" as in IEnumerable, ICanMove, ICanLog, etc..
Charles Bretana
Interact, behavior are equivalent terms in this regard. That the classes are doing something that is defined by the interface.
RS Conley
+3  A: 

Having an abstract class lets you implement some/most of the members in a common way. Having an interface means you aren't restricted to only using that abstract base class when you want to use it for polymorphism.

I don't see any contradiction in having both.

Jon Skeet
+1  A: 

Interfaces provide you the ability to have polymorphic behaviour across class heirachy's. The downside is that you can't inherit a default implementation (directly). With class polymorphism you can only get that polymorphic behaviour within your class heirachy, but you can inherit common/default behaviour. By inherting and providing an interface you provide a contract (the interface) but get the easy implementation benefits of inheritance while still allowing others to support the "contract" outside of the baseclass limitations.

Tim Jarvis
A: 

Base classes and interfaces really have mostly unrelated purposes. The main purpose of the base class is for your inheriting class to be able to import some common functionality. The main purpose of the interface is for other classes to be able to ask the question, "does this object support interface X"?

chaos
Although I disagree with your comment, I did not down vote you.What's the difference between an Abstract class with only public methods and an Interface with the same methods implemented?
Chuck Conway
Mainly that in a single-inheritance model, your abstract class prevents the inheritors from inheriting anything else and your interface doesn't.
chaos
I'd really like to ask my downvoter what they think interfaces are for... do you imagine their purpose is as some kind of implementation guide, or what?
chaos
I have a sneaking suspicion that many people downvote just to keep their answers up there... or just because they don't like your name...
Jason Coco
A: 

So I guess I could inherit an animal class for common behaviour, like walk, sleep, etc, and then have a specialised interface (for a lion, perhaps), which would contain specific behaviour and properties - like the animal is dangerous, eats humans, etc.

dotnetdev
+1  A: 

Interfaces enforce "Behavior". Any class that is declared to implement a specified interface MUST implement members with the signatures declared in the interface.. i.e, they must publically that specified behavior... They don't necessarly have to implement the behavior in the same way, but they musrt be capable of the same behavior... i.e. both a bird and a worm "CanMove", so they both must implement the behavior" of being able "to Move", Specifying that they both must impement interface ICanMove does this... How they do it is the function of implementation.

Base classes are for reuse of "Implementation"...

That's why naming conventions for interfaces suggest using "I[Verb/Adverb]" as in IEnumerable, ICanMove, ICanLog, etc.

You use base classes to put common implementation in a single place. If an abstract base class has no implementation, in any member, then it functions identically to an interface, which cannot have implementation

Charles Bretana
+4  A: 

The statement that "inheriting from a base class allows you to inherit BEHAVIOR, whereas implementing an interface only lets you specify INTERACTION" is absolutely true.

But more importantly, interfaces allow statically typed languages to continue to support polymorphism. An Object Oriented purist would insist that a language should provide inheritance, encapsulation, modularity and polymorphism in order to be a fully-featured Object Oriented language. In dynamically-typed - or duck typed - languages (like Smalltalk,) polymorphism is trivial; however, in statically typed languages (like Java or C#,) polymorphism is far from trivial (in fact, on the surface it seems to be at odds with the notion of strong typing.)

Let me demonstrate:

In a dynamically-typed (or duck typed) language (like Smalltalk), all variables are references to objects (nothing less and nothing more.) So, in Smalltalk, I can do this:

|anAnimal|    
anAnimal := Pig new.
anAnimal makeNoise.

anAnimal := Cow new.
anAnimal makeNoise.

That code:

  1. Declares a local variable called anAnimal (note that we DO NOT specify the TYPE of the variable - all variables are references to an object, no more and no less.)
  2. Creates a new instance of the class named "Pig"
  3. Assigns that new instance of Duck to the variable anAnimal.
  4. Sends the message makeNoise to the pig.
  5. Repeats the whole thing using a cow, but assigning it to the same exact variable as the Pig.

The same Java code would look something like this (making the assumption that Duck and Cow are subclasses of Animal:

Animal anAnimal = new Pig();
duck.makeNoise();

anAnimal = new Cow();
cow.makeNoise();

That's all well and good, until we introduce class Vegetable. Vegetables have some of the same behavior as Animal, but not all. For example, both Animal and Vegetable might be able to grow, but clearly vegetables don't make noise and animals cannot be harvested.

In Smalltalk, we can write this:

|aFarmObject|
aFarmObject := Cow new.
aFarmObject grow.
aFarmObject makeNoise.

aFarmObject := Corn new.
aFarmObject grow.
aFarmObject harvest.

This works perfectly well in Smalltalk because it is duck-typed (if it walks like a duck, and quacks like a duck - it is a duck.) In this case, when a message is sent to an object, a lookup is performed on the receiver's method list, and if a matching method is found, it is called. If not, some kind of NoSuchMethodError exception is thrown - but it's all done at runtime.

But in Java, a statically typed language, what type can we assign to our variable? Corn needs to inherit from Vegetable, to support grow, but cannot inherit from Animal, because it does not make noise. Cow needs to inherit from Animal to support makeNoise, but cannot inherit from Vegetable because it should not implement harvest. It looks like we need multiple inheritance - the ability to inherit from more than one class. But that turns out to be a pretty difficult language feature because of all the edge cases that pop up (what happens when more than one parallel superclass implement the same method?, etc.)

Along come interfaces...

If we make Animal and Vegetable classes, with each implementing Growable, we can declare that our Cow is Animal and our Corn is Vegetable. We can also declare that both Animal and Vegetable are Growable. That lets us write this to grow everything:

List<Growable> list = new ArrayList<Growable>();
list.add(new Cow());
list.add(new Corn());
list.add(new Pig());

for(Growable g : list) {
   g.grow();
}

And it lets us do this, to make animal noises:

List<Animal> list = new ArrayList<Animal>();
list.add(new Cow());
list.add(new Pig());
for(Animal a : list) {
  a.makeNoise();
}

The biggest advantage to the duck-typed language is that you get really nice polymorphism: all a class has to do to provide behavior is provide the method (there are other tradeoffs, but this is the big one when discussing typing.) As long as everyone plays nice, and only sends messages that match defined methods, all is good. The downside is that the kind of error below isn't caught until runtime:

|aFarmObject|
aFarmObject := Corn new.
aFarmObject makeNoise. // No compiler error - not checked until runtime.

Statically-typed languages provide much better "programming by contract," because they will catch the two kinds of error below at compile-time:

Animal farmObject = new Corn();  // Compiler error: Corn cannot be cast to Animal.
farmObject makeNoise();

--

Animal farmObject = new Cow();
farmObject.harvest(); // Compiler error: Animal doesn't have the harvest message.

So....to summarize:

  1. Interface implementation allows you to specify what kinds of things objects can do (interaction) and Class inheritance lets you specify how things should be done (implementation).

  2. Interfaces give us many of the benefits of "true" polymorphism, without sacrificing compiler type checking.

Jared