Inheritance, composition and default methods

前端 未结 5 692
日久生厌
日久生厌 2021-02-08 05:28

It is usually admitted that extending implementations of an interface through inheritance is not best practice, and that composition (eg. implementing the interface again from s

5条回答
  •  天命终不由人
    2021-02-08 05:58

    It is usually admitted that extending implementations of an interface through inheritance is not best practice, and that composition (e.g. implementing the interface again from scratch) is more maintainable.

    I don't think that this is accurate at all. For sure there are lots of situations where composition is preferred over inheritance, but there are lots of situations where inheritance is preferred over composition!

    Its especially important to realise that the inheritance structure of your implementation classes need not look anything like the inheritance structure of your API.

    Does anyone really believe, for example, that when writing a graphical library like Java swing every implementation class should reimplement the paintComponent() method? In fact a whole principal of the design is that when writing paint methods for new classes you can call super.paint() and that insures that all elements in the hierarchy are drawn, as well as handling the complications involving interfacing with the native interface further up the tree.

    What is generally accepted is that extending classes not within your control that were not designed to support inheritance is dangerous and potentially a source of irritating bugs when the implementation changes. (So mark your classes as final if you reserve the right to change your implementation!). I doubt Oracle would introduce breaking changes into ArrayList implementation though! Provided you respect its documentation you should be fine....

    Thats the elegance of the design. If they decide that there is a problem with the ArrayList, they will write a new implementation class, similar to when they replaced Vector back in the day, and there will be no need to introduce breaking changes.

    ===============

    In your current example, the operative question is: why does this class exist at all?

    If you are writing a class which extends the interface of list, which other methods does it implement? If it implements no new methods, what is wrong with using ArrayList?

    When you know the answer that you will know what to do. If the answer "I want an object which is basically a list, but has some extra convenience methods to operate on that list", then I should use composition.

    If the answer is "I want to fundamentally change the functionality of a list" then you should use inheritance, or implement from scratch. An example might be implementing an unmodifiable list by overriding ArrayList's add method to throw an exception. If you are uncomfortable with this approach you might consider implementing from scratch by extending AbstractList, which exists precisely to be inherited from to minimise the effort of reimplementation.

提交回复
热议问题