This is somewhat of a follow-up question to this question.
Suppose I have an inheritance tree as follows:
Car -> Ford -> Mustang -> MustangGT
Is there a benefit to defining interfaces for each of these classes? Example:
ICar -> IFord -> IMustang -> IMustangGT
I can see that maybe other classes (like Chevy
) would want to implement Icar
or IFord
and maybe even IMustang
, but probably not IMustangGT
because it is so specific. Are the interfaces superfluous in this case?
Also, I would think that any class that would want to implement IFord
would definitely want to use its one inheritance by inheriting from Ford
so as not to duplicate code. If that is a given, what is the benefit of also implementing IFord
?
You shouldn't implement any of those interfaces at all.
Class inheritance describes what an object is (eg: it's identity). This is fine, however most of the time what an object is, is far less important than what an object does. This is where interfaces come in.
An interface should describe what an object does), or what it acts like. By this I mean it's behavior, and the set of operations which make sense given that behaviour.
As such, good interface names should usually be of the form
IDriveable
,IHasWheels
, and so on. Sometimes the best way to describe this behaviour is to reference a well-known other object, so you can say "acts like one of these" (eg:IList
) but IMHO that form of naming is in the minority.Given that logic, the scenarios where interface inheritance makes sense are completely and entirely different from the scenarios where object inheritance makes sense - often these scenarios don't relate to eachother at all.
Hope that helps you think through the interfaces you should actually need :-)
I'd say only make an interface for things you need to refer to. You may have some other classes or functions that need to know about a car, but how often will there be something that needs to know about a ford?
Think carefully about how your objects need to interact with each other within your problem domain, and consider if you need to have more than one implementation of a particular abstract concept. Use Interfaces to provide a contract around a concept that other objects interact with.
In your example, I would suggest that Ford is probably a Manufacturer and Mustang is a ModelName Value used by the Manufacturer Ford, therefore you might have something more like:
IVehichle -> CarImpl, MotorbikeImpl - has-a Manufacturer has-many ModelNames
In this answer about the difference between interface and class, I explained that:
So if you need to store into a 'Ford' variable (notion of 'value') different sub-classes of Ford, create an IFord. Otherwise, do not bother until you actually need it.
That is one criteria: if it is not met, IFord is probably useless.
If it is met, then the other criteria exposed in the previous answers apply: If a Ford has a richer API than a Car, an IFord is useful for polymorphisms purpose. If not, ICar is enough.
I also agree with adamalex's response that interfaces should be shared by classes that should respond to certain methods.
If classes have similar functionality, yet are not directly related to each other in an ancestral relationship, then an interface would be a good way to add that function to the classes without duplicating functionality between the two. (Or have multiple implementations with only subtle differences.)
While we're using a car analogy, a concrete example. Let's say we have the following classes:
Cars have
wheels
and canDrive()
andSteer()
. So those methods should exist in theCar
class. (Probably theCar
class will be an abstract class.)Going down the line, we get the distinction between
Ford
andToyota
(probably implemented as difference in the type of emblem on the car, again probably an abstract class.)Then, finally we have a
Escape
andCorolla
class which are classes that are completely implemented as a car.Now, how could we make a Hybrid vehicle?
We could have a subclass of
Escape
that isEscapeHybrid
which adds aFordsHybridDrive()
method, and a subclass ofCorolla
that isCorollaHybrid
withToyotasHybridDrive()
method. The methods are basically doing the same thing, but yet we have different methods. Yuck. Seems like we can do better than that.Let's say that a hybrid has a
HybridDrive()
method. Since we don't want to end up having two different types of hybrids (in a perfect world), so we can make anIHybrid
interface which has aHybridDrive()
method.So, if we want to make an
EscapeHybrid
orCorollaHybrid
class, all we have to do is to implement theIHybrid
interface.For a real world example, let's take a look at Java. A class which can do a comparison of an object with another object implements the
Comparable
interface. As the name implies, the interface should be for a class that is comparable, hence the name "Comparable".Just as a matter of interest, a car example is used in the Interfaces lesson of the Java Tutorial.
In general, the best way to think about this (and many questions in OO) is to think about the notion of a contract.
A contract is defined as an agreement between two (or more) parties, that states specific obligations each party must meet; in a program, this is what services a class will provide, and what you have to provide the class in order to get the services. An interface states a contract that any class implementing the interface must satisfy.
With that in mind, though, your question somewhat depends on what language you're using and what you want to do.
After many years of doing OO (like, oh my god, 30 years) I would usually write an interface for every contract, especially in Java, because it makes tests so much easier: if I have an interface for the class, I can build mock objects easily, almost trivially.