super or not

I ran across the following in the java.lang.Properties code:

public String getProperty(String key){

Object oval = super.get(key);

String sval = (ovalinstanceof String) ? (String)oval :null;

return ((sval ==null) && (defaults !=null)) ? defaults.getProperty(key) : sval;

}

IMHO, the first line should have been writted as

Object oval = this.get(key);

The reason is that its subclass may decide to override the get method! Now nobody can override the get method in a subclass of Properties. Very miserable! Any disagreement?

[840 byte] By [weica] at [2007-9-30 23:58:53]
# 1

read again...

super.get(String) calls the superclass get method of java.lang.Properties always, also in derived classes.

If you inherit from java.lang.Properties and call getProperty(String) the method on java.lang.Properties will get called unless you've overridden it in which case the code in the overridden method won't get executed.

jwentinga at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 2

The class Properties is derived from Hashtable. It is meant to handle Strings, whereas Hashtable can handle any Object. In C++ there is private inheritance, where a class is implemented with the help of its ancestor class without inheriting its interface. In this case an object of the derived class is not considered to be of the type of the ancestor class! There is no such thing in Java.

I think writing it this way is a stylistic hint that we use the "get" method of super class, that is, we rely upon the implementation of the super class which can yield a String or something else.

super.get(String)

BIJ001a at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 3

My point in the reply seems completely missed. In an OO environment, you use super when

1) override the same method

2) when overriding different method, without super, the execution will come back to the method.

The first one doesn't hold, since getproperties is not being overriden. The second doesn't hold, since getproperties is a new method, and there is no overriding for get method.

Now with super, it loses a great OO feature: inheritance. That is, the writer of subclass to properties cannot override get method to provide a conherence implementation for get method, because getproperty violates the inheritance rule.

Hope this clarifies.

weica at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 4
no, YOU missed the point so completely it seems you have no grasp of things at all.Read my initial reply again... super will call the superclass of the class the method was defined in, NOT the superclass of the class the method was called from.
jwentinga at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 5
I don't have disagreement with your understanding how super works. My point is still: what is the reason to use super when the effect would be the same without super. I presented the rules of thumb, so read again.
weica at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 6

the effect would not be the same if the class itself overrides the superclass method.

Say you have a method doSomething(boolean) in your superclass and provide an overridden implementation in your own class.

At some point (possibly in your own re-implementation) you need to call the original version, that's when you use super.doSomething(true) (for example).

It may not (depending on use, if in the overriding method it's fine) good OO design, but it doesn't prevent inheritance as you claimed (or alleged).

jwentinga at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 7

> the effect would not be the same if the class itself

> overrides the superclass method.

>

> Say you have a method doSomething(boolean) in your

> superclass and provide an overridden implementation

> in your own class.

> At some point (possibly in your own

> re-implementation) you need to call the original

> version, that's when you use super.doSomething(true)

> (for example).

First of all, that meets the OP's criterion of using "super" when overriding the same method. Second of all, what if (for example) a future developer wishes to add a DoSomethingListener that notifies objects if doSomething() is called? The code usage in java.lang.Properties would ignore an addition like that.

The worry, of course, is that the overriding implementation might break the contract of the original method; getProperties() might be coded to assume a specific behavior from get(), and may break if that behavior is not exhibited.

I'm not sure what the "official" OO-kosher policy is, but I think that's the responsibility of the future developer; they should ensure that their version of the function calls the superclass function if there are any side-effects or expected behaviors.

PierceHanleya at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 8

I think that PierceHanley got my point. If everybody used super, there would be no inheritance or overriding, thus no OO. Btw, I just got a reply from Sun agreeing that this is a bug:

"

We have determined that this report is a new bug and entered the bug into our

internal bug tracking system under Bug Id: 6206254.

You can monitor this bug and look for related issues on the Java Bug Database at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6206254

It may take a day or two before your bug shows up in this external database.

"

Thanks for everybody's replies.

weica at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 9

Guess what? Some developer closed the bug without fixing. It might be that he does not understand what OO principles are or it's too embarassing for him to admit mistakes. Sigh

The guy at Sun who reviewed and posted it as a bug has a big sigh on this too. I believe if it would Bill's company his engineer would fix it.

weica at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 10

I can understand their argument; given a black-box implementation of Properties, there's no reason to assume that Properties.getProperty necessarily calls Properties.get, so the implementors of getProperty should be able to do whatever is most useful for them.

However, thinking about it, the conceptual purpose for making Properties extend Hashtable would be so that Hashtable.get could be a synonym for Properties.getProperty. But in actuality (from the Properties javadoc):

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead. If the store or save method is called on a "compromised" Properties object that contains a non-String key or value, the call will fail.

This seems like the real bug; if put and putAll are discouraged, especially if they leave the object in a "compromised" state, then they should either be overridden with safe versions of themselves (even if that means throwing an IllegalArgumentException), or not be available at all. In other words, someone writing a function that receives a Hashtable should not have to concern themselves with the idea that ht.put(new Integer(5),"five"); will apparently succeed, but leave their object in an inconsistent state.

This seems to be representative of a larger problem with Properties, in that it (A.) is close enough to Hashtable in concept that it's desireable to be able to treat it like one, and (B.) conceptually has more of a has-a relationship with Hashtable, as the data source for its information.

PierceHanleya at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 11

So to sum up the problems with the current definition of Properties:

1. Unclear relationship with Hashtable. Some java developer needs to figure out whether a Properties definition is-a Hashtable, or whether it has-a Hashtable.

1a. Within the current inheritance, inconsistent policy regarding subclassing. "getProperty" uses super.get(), meaning that it will get the property from the HashMap. "setProperty" uses simply put(), meaning that its behavior could potentially be changed by subclassing.

1b. Properties are supposed to be string-string mappings, yet (now that J2SE 5 makes that behavior definable) it extends Hashtable<Object,Object>. If it's going to extend Hashtable at all, it should extend Hashtable<String,String>.

2. Poor safety. The class is intentionally designed to make an unsafe behavior possible, and yet there is no safeguard against that behavior until it is too late. Imagine the following code:public void shouldBeOkay() {

Properties props = new Properties();

setMappings(props);

useAProperty(props);

storeMyProperties(props);

}

public void setMappings(Hashtable props) {

props.put("safe.property","I am happy.");

props.put("unsafe.property", new Integer(5));

}

public void useAProperty(Properties props) {

String safeValue = props.getProperty("safe.property"); // safeValue is "I am happy"

String unsafeValue = (String) props.get("unsafe.property");

/* ClassCastException? wtf? I thought "Properties" objects only had strings

as keys/values? */

/*** OR... ***/

int unsafeValueLength = props.getProperty("unsafe.property").length();

/* NullPointerException? wtf? I know the property "unsafe.property" was

set, what went wrong? It's even in the "propertyNames()" enumeration,

which would seem to indicate that it's safe! */

}

public void storeMyProperties(Properties props) {

/* HERE is where the described behavior of a "compromised" Properties

object is exhibited. Note that this is not until other errors have been exposed

from previous usage of this object. */

props.store(new FileOutputStream("My.properties"));

}

... these relatively trivial and obvious uses of the Properties class are completely broken, even though they would supposedly be safe according to the javadoc.

3. Use of obsolete classes. propertyNames() is exposed as an enumeration, rather than a set or list or iterator as would make more sense. Also, it extends Hashtable which extends Dictionary, which is an obsolete class which was apparently added to the API by someone who didn't know what an interface was (empty default constructor, and nothing else but abstract methods). I mean for crying out loud, it's been obsolete since JDK 1.2. Can we please inconvenience the poor schmoes who are still using this thing? They really deserve it.

Maybe Sun is intentionally leaving this class broken so that people will move to more mature preference systems (like those in the java.util.prefs package). But if that's the case, then they should really deprecate Properties IMO.

PierceHanleya at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 12

Sorry to be spamming a bit, but I came across these in the JDK bug database:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4880089

"We do not intend to further evolve the legacy Properties class and so we will not add a new method to report the "real" size of a Properties list."

...and:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4744940

"This is an unfortunate side effect of the poor design decision of making Properties extend Hashtable instead of delegating to a Hashtable (or HashMap).

We are not further evolving this legacy class so this flaw must remain."

At least they realize that that was a bad idea. So the question is, why are they unwilling to migrate away from it? I know it's the primary (only?) means of accessing system parameters (classpath, jvm version, etc) through the System.getProperty methods, but why don't they practice what they preach and use the newer preference systems for that purpose?

PierceHanleya at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 13

No matter what, the bad code is the bad code. Any seasoned programmer would never use super in the way as written in the getProperty method. This fact doesn't change no matter how it is documented.

Sun has to be less arrogant and listen to others. One example Sun needs to study is Steve Job's NextStep, which was a 15 year old technology, but still the best OO system ever developed.

weica at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...
# 14

The reason to not change the implementation of Properties at this stage is likely best summed up as:

1) not wishing to break existing applications that (ab)use it (iow, backwards compatibility).

2) not wishing to spend time rewriting a class which may well be deprecated soon (who knows, maybe Mustang will see Properties deprecated).

After all, ResourceBunble is now preferred over Properties.

jwentinga at 2007-7-7 15:43:02 > top of Java-index,Administration Tools,Sun Connection...