some notes on inheritance, especially private inheritance and java interfaces.
basically I'm wondering about the pros and cons of having readonly in Java but creating an interface that is readonly (one that has only the read-only methods available at compile-time, unlike java.util.Collections.unmodifiableList). (and you can read Core Java 2 for comments).
- In particular, one disadvantage with my proposal of having only the read-only methods available, is that the interface would be returning types not of, say, List, but of I_ReadOnlyList. And how much would that mess up other code? A lot of other code depends on "List", specifically. Such a situation of trying to use I_ReadOnlyList everywhere might be analogous to the const problem in C++, in which code that is not anticipating const is very hard to connect to.
- One solution is to cast back to a List, but then you get access to writeable methods. You could call java.util.Collections.unmodifiableList() on this. You could standardize this by having a I_ReadOnlyList method that does a list-view, called "unmodifiableList()", which would wrap the I_ReadOnlyList implementation with a class that intercepts all writeable method calls with methods that throw runtime exceptions, and the class would be of interface type List. (You could probably implemnt this with java.util.Collections.unmodifableList( (List)_readOnlyList ). But obviously this doesn't help things at compile time. But at least it protects you at compile time.
Research notes. Allen Holub of Javaworld.
i like this guy.
"Personally I always keep class hierarchies package private. None of the types participating in class implementation ever escapes the package, only interfaces do. In this way class implementation is totally detached from the public types of the design. A user of the package cannot instantiate anything but has to ask for objects (of an interface type) by calling create methods.
The above is a practical way to achieve a clean separation of implementation inheritance from type inheritance. With this in place multiple inheritance of implementation would do no harm. It's just a convenient way to reuse code. It could be compared to private inheritance in C++. No types get exposed in the process. "
Later, "So to rephrase my Java design strategy. Try to contain implementation within packages, only expose abstract types between packages. Do this unless you have very good reasons to expose concrete classes. "
Note according to this page, http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html
, the implies Gosling said to declare variable as interface types or primitives, never classes, but to avoid using using implementation inheritance. (avoid the extends keyword). I note with generics, the only way to have a type parameter implement an interface is with the extends keyword, not the implments keyword, so I presume Gosline would make an exception there!
Note template parameter should avoid extending classes, just interfaces. (and maybe abstract classes are ok).
This article also encourages the use of passing "Iterator" instead of Collection, for flexibility. (because you can iterate through views of a map, but a map is not a collection? huh? i think all iterable views of a map (keySet, values, and entrySet, ARE collections.) I further note, that since I read Java wants you to pass groups, not iterators, you could pass something of type Iterable (assuming any class designer who has a method creating an Iterator is also going to remember to implement Iterable. which isn't true in general. oh well.)
I suppose javaworld's suggestion of avoiding protected fields is good. He doesn't really offer a solution. I think getters and setters would be the best solution.
i don't understand this Allen Holub person from javaworld. "(You can occasionally use protected methods effectively, but protected instance variables are an abomination.) You should never use get/set functions for the same reason—they're just overly complicated ways to make a field public (though access functions that return full-blown objects rather than a basic-type value are reasonable in situations where the returned object's class is a key abstraction in the design).
- I think a get and set are a problem if you assume they NEVER do nothing else but connect to the field. but i think they're great because then you can have them do more besides connect to the field (like check preconditions and invariants, and update cached variables).
- I have realized before that get and set are a problem if they let the user modify internal state without going through the class's public methods. (and they are a problem if they expose the implementation; someone could make assumptions about the implementation, and the assumptions could be wrotng. also a problem with exposing the implmentation is that someone could maybe read infrmation that ought to be security.)
Also, I note with a class with a lot of methods it is awkward to forward them all. It makes for cluttered code that is hard to maintain. Eclipse has generate the initial forward calls, but Eclipse does not maintain them. And even if Eclipse did automatically maintain, then you would probably get the problems of implementation inheritance back. So how could one specify to Eclipse in a good way about when this forwarding-class should be updated and when not?
the isa relationship is sometimes confusing. should we say a conceptual stack isa conceptual list? or a conceptual list isa conceptual stack? Because a stack could be implemnted as a list with private inheritance. or a list might be able to be implmented by PUBLICLY implementing. with a stack if the stack's fields are protected (not private). Both ways are "impure" - although at least one might certainly be useful!
- (yes, perhaps no one really said private inheritance is ISA. Except that conceptually, I think a lot of people would say a Stack IS A special type of a List! So I'll say it now, private inheritance is ISA a bit intuitively).
Holub notes a problem with implementation inheritance. Any base class modifying state could fail to update a derived class field. So I agree with him that one solution is override all base class methods that update state. And in this case, I agree (for a small implemtnation of Stack), to avoid extends, and to simply forward on all calls.
, to explain: author is saying if someone were to CALL PUSH_MANY() on the DERVIED class MonitorableStack?
, then MonitorableStack?
uses the inherited push_many() from Stack, and would deliberately affect push_many by overriding push.
* So how does getting rid of implementation inheritneace avoid this problem? I note that it forces MonitorableStack?
to implement push_many() itself, and not assume anything about Stack's push_many().
this interview from 2002 with Scott Myers of "Effective C++" is in a good style. "this were my experiences. what is your opnion" - type style.
- ABC= Abstract Base Class, i assume.
- the article says, "Second, even some of the people who had used multiple inheritance didn't have great things to say about it. Notably, Jerry Schwartz, who had implemented the IO streams library based on multiple inheritance, had publicly said that if he had it to do over again he would not use multiple inheritance. He would find some way to get rid of the multiple inheritance. " !!!
- Scott Meyers basically says the C++ community got distracted by perfecting the language. "The end result is, we have templates in C++, but there's no way to write user interfaces or talk to databases. ". "The standard library for C++ is pretty impoverished." So, he's saying, the language people have created something good, but they are losing the race because they took time to do it, and didn't make huge standard libraries in the meantime.
this might help: http://www.objectmentor.com/resources/articles/privateInterface.pdf
but some parts are hard to read. holub is fairly easy to read.
i liked this http://scottcollins.net/blog/2005/11/re-jay-r-wrens-clarifying-things-i.html
TODO: see what John Boyland wrote on this. and see my paper notes. http://www.google.com/search?q=java+private+inheritance+interface+boyland&rls=com.microsoft:en-us:IE-SearchBox&ie=UTF-8&oe=UTF-8&sourceid=ie7&rlz=1I7SUNA
- 08 Nov 2007