开发者

How to move away from Inheritance

I've searched in here and other forums and couldn't find a good answer.. I kind of know that Extending classes isn't the best of practices. And that I should use Interfaces more. my problem is that usually I start creating Interfaces and then move to Abstract classes because there's always some functionality that I want implement开发者_Python百科ed on a super class so that I don't have to replicate it in every child classes. For instance, I have a Vehicle class and the Car and Bike child classes. a lot of functionality could be implemented on the Vehicle class, such as Move() and Stop(), so what would be the best practice to keep the architecture clean, avoid code repetition and use Interfaces instead of Inheritance? Thanks a lot!

(if you have no idea why I'm asking this you may read this interesting article: http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html)


Inheritance ('extending classes') imposes significant limitations on class design and I'm not sure the use of interfaces as a replacement for inheritance is the best idea since it fails the DRY test.

These days, Composition is favored over Inheritance, so you might consider this post: Prefer composition over inheritance?


Interesting question. Everyone has different approaches. But it all based on personal experience and choice.

Usually, i start with an interface, then let an abstract class inherit that interface. And implement common actions there, and let others to be implemented by who ever inherits this class.

This give few advantageous based on by experience,
1.During function calls you can pass the elements as interface type or abstract class type.
2.Common variables such as ID, Names etc can be put on abstract class.
3.Easy for maintenance. For example, if you want to implement a new interface, then just implement in the abstract quickly.


If you keep in mind fundamental difference between interfaces and classes it will make it easier to decide which one to use. The difference is that interfaces represent just a protocol (usually behavioral) between objects involved, while abstract classes represent some unfinished constructions that involve some parts (data). In car example, interface is essentially a blueprint for the generic car. And abstract class would be like prefabricated specific model car body that needs to be filled with remaining parts to get final product. Interfaces don't even have to be in Java - it will not change anything - still blueprint.

Typically you would use abstract class within your specific implementation framework to provide its consumers with some basic functionality. If you just state that you never use abstract class in favor of interface - it's plain wrong from practical standpoint. What if you need 10 implementations of the same interface with 90% of the same code. Replicate code 10 times? Ok, may be you would use abstract class here but put interface on top of it. But why would you do that if you never intend to offer your class hierarchy to external consumers? I am using word external in very wide sense - it can be just different package in your project or remote consumer.

Ultimately, many of those things are preferences and personal experiences, but I disagree with most blanket statements like extends is evil. I also prefer not to use extra classes (interfaces or abstract) unless it is required by specific parts of the design.

Just my two cents.


Inheritance allows code reuse and substitutability, but restricts polymorphism. Composition allows code reuse but not substitutability. Interfaces allow substitutability but not code reuse.

The decision of whether to use inheritance, composition, or interfaces, boils down to a few simple principles:

  1. If one needs both code reuse and substitutability, and the restrictions imposed on polymorphism aren't too bad, use inheritance.

  2. If one needs code reuse, but not substitutability, use composition.

  3. If one needs substitutability, but not code reuse, or if the restrictions inheritance would impose upon polymorphism would be worse than duplicated code, use interfaces.

  4. If one needs substitutability and code reuse, but the restrictions imposed by polymorphism would be unacceptable, use interfaces to wrap encapsulated objects.

  5. If one needs substitutability and code reuse, and the restrictions imposed by polymorphism would not pose any immediate problem but might be problematic for future substitutable classes, derive a model base class which implements an interface, and have those classes that can derive from it do so. Avoid using variables and parameters of the class type, though--use the interface instead. If you do that, and there is a need for a substitutable class which cannot very well derive from the model base class, the new class can implement the interface without having to inherit from the base; if desired, it may implement the interface by wrapping an encapsulated instance of a derivative of the model type.

Judgment may be required in deciding whether future substitutable classes may have difficulty deriving from a base class. I tend to think approach #5 often offers the best of all worlds, though, when substitutability is required. It's often cheaper than using interfaces alone, and not much more expensive than using inheritance alone. If there is a need for future classes which are substitutable but cannot be derived from the base, it may be necessary to convert the code to use approach #5. Using approach #5 from the get-go would avoid having to refactor the code later. (Of course, if it's never necessary to substitute a class that can't derive from the base, the extra cost--slight as it may be--may end up being unnecessary).


Agree with tofutim - in your current example, move and stop on Vehicle is reasonable.

Having read the article - I think it's using powerful language to push a point... remember - inheritance is a tool to help get a job done.

But if we go with the assumption that for whatever reasons you can't / won't use the tool in this case, you can start by breaking it down into small interfaces with helper objects and/or visitors...

For example - Vehicle types include submarine, boat, plane, car and bike. You could break it down into interfaces... IMoveable + Forward() + Backward() + Left() + Right()

IFloatable + Dock()

ISink() + BlowAir()

IFly() + Takeoff() + Land()

And then your classes can aggregate the plethora of interfaces you've just defined.

The problem is though that you may end up duplicating some code in the car / bike class for IMoveable.Left() and IMoveable.Right(). You could factor this into a helper method and aggregate the helper... but if you follow it to its logical conclusion, you would still end up refactoring many things back into base classes.

Inheritance and Aggregation are tools... neither of which are "evil".

Hope that helps.


Do you want an answer for your specific case, or in general? In the case you described, there is nothing wrong with using an Abstract class. It doesn't make sense use an interface when all of the clients would need to implement the exact same code for Move() and Stop().


  • Don't believe all you read

    • Many times, inheritance is not bad, in fact, for data-hiding, it may be a good idea.
  • Basically, only use the policy of "interfaces only" when you're making a very small tree of classes, otherwise, I promise it will be a pain. Suppose you have a Person "class" (has eat() and sleep), and there are two subclasses, Mathematician (has doProblem() ) and Engineer ( buildSomething() ), then go with interfaces. If you need something like a Car class and then 56 bazillion types of cars, then go with inheritance.

IMHO.


I think, that Interfaces sometime also evil. They could be as avoidance of multiple inheritance.

But if we compare interface with abstract class, then abstract class is always more than interface. Interface is always some aspect of the class -- some viewpoint, and not whole as a class.

So I don't think you should avoid inheritance and use iterfaces everywhere -- there should be balance.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜