"COMPUTER POWER TO THE PEOPLE! DOWN WITH CYBERCRUD!" - Theodor Nelson
My StuffLoveRespectAdmiration
My AmpsLinksArchives
![]() ![]()
|
Monday, September 08, 2003
More on final
More from the PragProg list: >From: Ged Byrne >In 'Effective Java' Bloch goes to the other extreme. > >Item 15 is "Design and document for inheritance or >else prohibit it." Basically, every class should be >Final unless you have specifically designed for >inheritance. > >http://java.sun.com/docs/books/effective/toc.html > >His argument is that inheritance provides an >additional interface to your objects. If you allow >somebody to extend your objects in a way that you >never imagined, then you are forced to either always >support that unintended use for the entire life of the >object or upset users of your interface when things >change. I think making your objects all final is going way to far. I generally make my internal data local to my class, but expose the methods for accessing to be protected. I think people should write lots of little methods and override where you need to in subclassing. I generally take a more responsiblity driven approach to my design. I tend to think of the interface before the internal data implementation. If you provide accessors for your internal structure and make sure that only subclasses have access. I think you should only make things public that you must. But, subclasses should have access to all of its superclasses' methods and not their instance variables. This forces subclasses to use the accessors. If you change this aspect, generally you can deprecate the accessors and put in an implementation in the method that wraps the internals if that makes sense. Generally, I use a lot of interfaces whenever I can and avoid primitive types. I also find that staying true to the law of demeter also reduces the exposure of internals changing on the subclasses. >One of the promises of OO is that behind the interface >you can change all of the internal workings. I might >start off by writing an object that keeps some data in >a persisted array. As the objects grows the array is >too small and become a problem, so it is replaced by a >database table. You see I would make the persisted array an object in of itself and expose it via an interface. If I needed to change the implementation, then I would be changing the persisted array and not the class that's holding on to it. >If you OO has a tight interface, then you make the >change to just this one object and your done. Exactly! >If, on the other hand, your object exposed the >internal array to subclasses and these subclasses use >the array directly then when you update the object you >either have to write a pseudo proxy that will behave >just like the array to subclasses or rewrite all the >subclasses. Yes. My point would be to make sure that the persisted array has its on interface. I use interfaces a lot in Java because I only care if an object implements a protocol and not what it is per se. I just care that I get something that implements that interface and I don't care how it does it behind the scenes. I find interfaces and keeping with the law of demeter helps my designs to be more flexible in this regard. If truth be told, My inheritence heirarchies are generally very shallow. They rarely get deeper than 3. I find polymorphism to be a much more useful abstraction in terms of making my objects less coupled. Also, my super classes generally tend to be more of the template pattern where the subclasses are just providing different functionality at different points and interacts very little with the super class. >So, by this argument (don't know if I entirely agree) >if you expose your objects internals then you are >saying 'the internal implementation is perfect. I >will never have to change it, so do whatever you want >with it.' I don't view subclassing as "exposing your internals", but I can see where you're going with it. I think a subclass is still behind the lines. I think subclass takes on the responsibility of if the superclass changes, then I must change as well. I do not think it's up to the super class owner to make sure his code works with all possible subclasses. I think it's nice for the super class owner to provide upgrade paths via deprecating methods and putting in workarounds, but not necessary. I have not found the changing super class to a problem on any system that I've worked on. Good design always makes things easier. |
Comments