Why is this not allowed ?

Hi,

interface IntegerComparableextends Comparable<Integer>{}

interface StringComparableextends Comparable<String>{}

class Testimplements SelfComparable, StringComparable{

publicint compareTo(Integer o){

return 0;

}

publicint compareTo(String o){

return 0;

}

}

Why is the above not allowed ?

Thanks,

Adrian

[1068 byte] By [AdrianSosialuka] at [2007-11-27 5:38:21]
# 1

Quirk of the language. An interface cannot be implemented more than once. Remember that generics are a source-level feature only, they don't exist at runtime. I'm betting that's the underlying reason: the JVM wouldn't see it implementing Comparable<String> and Comparable<Integer>, only that it implemented Comparable twice, which wouldn't make any sense at all

georgemca at 2007-7-12 15:11:46 > top of Java-index,Core,Core APIs...
# 2

Hi,

Thanks for your reply.

Yes, I understand that:

class MyClass implements Comparable<String>, Comparable<Integer>

is not acceptable because of the erasure. But since we derive from them

as in my previous example, event when the type parameters are dropped,

the class is implementing two different interfaces, which shouldn't be

a problem in my opinion. Note that when we drop type parameters

it is perfectly legal to do so ...

Perhaps you could write some example illustrating why it is not legal :)

Cheers,

Adrian

AdrianSosialuka at 2007-7-12 15:11:46 > top of Java-index,Core,Core APIs...
# 3

> Hi,

>

> Thanks for your reply.

>

> Yes, I understand that:

> > class MyClass implements Comparable<String>,

> Comparable<Integer>

>

> is not acceptable because of the erasure. But since

> we derive from them

> as in my previous example, event when the type

> parameters are dropped,

> the class is implementing two different interfaces,

> which shouldn't be

> a problem in my opinion.

Even though you've declared 2 separate interfaces, they are both still Comparables. Remember that there is no such class as Comparable<String>, only Comparable

In a nutshell, the compiler is smart enough to see through your ruse! Once erasure has been applied, your class is left with 2 identical methods declared upon it. That's a syntax error regardless of where these methods come from

> Note that when we drop type

> parameters

> it is perfectly legal to do so ...

>

> Perhaps you could write some example illustrating why

> it is not legal :)

Didn't you already do that? :-)

When you dropped the type parameters (from your sneaky interfaces, I presume) it becomes legal as a side effect. Your class may compile, but it won't behave as expected. It now implements Comparable, the raw type, and as such provides the compareTo(Object) method. Your class also has a compareTo(String) method, which is not derived from any interface, so if you had client code that wished to invoke the compareTo(String) method, it would have to have references of type MyClass, rather than the more useful Comparable<String> you had before

There may be times when your class needs to implement both of those methods, but it seems a bit smelly to me. Could an object really be comparable to objects of so many disparate types? There will always be a corner case that says "yes", but I bet there's a better way around it. Is this a real problem, or just mucking about?

georgemca at 2007-7-12 15:11:46 > top of Java-index,Core,Core APIs...
# 4

Hi,

Yeah - mucking about ;) I'm just learning this language and

want to know not only what I can and can't do but also why I can

do something and why not ...

Ohhh - I think I can see the problem now - after the erasure,

we get something like this:

interface StringComparable extends Comparable {}

interface IntegerComparable extends Comparable {}

class MyClass implements StringComparable, IntegerComparable {

public int compareTo(String o) {

return 0;

}

public int compareTo(Integer o) {

return 0;

}

public volatile int compareTo(Object o) {

return compareTo((?)o); // <-- what is the compiler supposed to insert here ?

}

}

IMHO, compiler could be smart enough and do some harder work ;)

It could insert something like this:

public int compareTo(Object o) {

Class c=o.getClass();

Map m=new HashMap();

m.put(String.class, new Integer(0));//these two it should know from

m.put(Integer.class, new Integer(1)); //interfaces declaration

int x=((Integer)m.get(c)).intValue();

int result=0;

switch(x) {

case 0: result=compareTo((Integer)o);

case 1: result=compareTo((String)o);

}

return result;

}

I'm not assuming it is the best solution (considering there will be small

amount of types, it could be an array and linear search or even if statements ...).

But I guess guys from Sun had good reasons not doing that. I just wonder

what they were ... ;)

Thanks,

Adrian

AdrianSosialuka at 2007-7-12 15:11:46 > top of Java-index,Core,Core APIs...
# 5

> Hi,

>

> Yeah - mucking about ;) I'm just learning this

> language and

> want to know not only what I can and can't do but

> also why I can

> do something and why not ...

>

> Ohhh - I think I can see the problem now - after the

> erasure,

> we get something like this:

> > interface StringComparable extends Comparable {}

> interface IntegerComparable extends Comparable {}

Exactly

> class MyClass implements StringComparable,

> IntegerComparable {

> public int compareTo(String o) {

> return 0;

> }

> public int compareTo(Integer o) {

> return 0;

> }

> public volatile int compareTo(Object o) {

> return compareTo((?)o); // <-- what is the

> he compiler supposed to insert here ?

> }

> }

>

>

> IMHO, compiler could be smart enough and do some

> harder work ;)

> It could insert something like this:

> > public int compareTo(Object o) {

> Class c=o.getClass();

> Map m=new HashMap();

> m.put(String.class, new Integer(0));//these

> se two it should know from

> m.put(Integer.class, new Integer(1)); //interfaces

> es declaration

> int x=((Integer)m.get(c)).intValue();

> int result=0;

> switch(x) {

>case 0: result=compareTo((Integer)o);

> case 1: result=compareTo((String)o);

> }

> return result;

> }

>

> I'm not assuming it is the best solution (considering

> there will be small

> amount of types, it could be an array and linear

> search or even if statements ...).

> But I guess guys from Sun had good reasons not doing

> that. I just wonder

> what they were ... ;)

>

>

> Thanks,

>

> Adrian

That's quite a special case for a compiler to deal with, though. Quite a lot of inferred intent, and probably a hotbed for bugs. While compiler optimizations are good, I for one wouldn't want a compiler silently inserting illogical code for me. For little benefit, too. If you need to compare an object to a totally different type, chances are you've got a design problem anyway. What object could be compared to both an Integer and a String, usefully? For the inevitable corner case, there would be better ways to achieve it. A method called compareAsString, for example. As a programmer reading someone elses code, seeing a class that could be compared to both String and Integer (or any other disparate types) would worry me

georgemca at 2007-7-12 15:11:46 > top of Java-index,Core,Core APIs...
# 6
Well, I guess it closes the thread and my worries :)Thank you very much for your help.Adrian
AdrianSosialuka at 2007-7-12 15:11:46 > top of Java-index,Core,Core APIs...
# 7

>

> IMHO, compiler could be smart enough and do some

> harder work ;)

Ah, the unspoiled enthousiasm of the beginner ;)

You have your logic backwards. The programmer is there to make sure the compiler doesn't have to work so hard, not the other way around.

Humans are still cheaper than CPU cycles in many areas, so it's cheaper to have the programmer work than to have the compiler do it.

jwentinga at 2007-7-12 15:11:46 > top of Java-index,Core,Core APIs...
# 8

One more thing about the propsed solution is that it suffers from the diamond problem. A class could implement two interfaces, say Foo and Bar. Then we come along and implement a class that's comparable to Foo and to Bar. Then we are passed an Object that implements both Foo and Bar. Which method does version of compareTo does the compiler use? This kind of problem is why interfaces were created in the first place.

dubwaia at 2007-7-12 15:11:46 > top of Java-index,Core,Core APIs...
# 9

That is an excellent point !

Thanks so much for it - I have just learned something new :)

It's because I was ONLY thinking about "raw" classes - I wasn't

thinking about interfaces. Coming back to example, I was thinking

that a class can be comparable to String OR Integer - not both

at the same time (since you can't inherit both from String and Integer

not saying about String being final ...) but that was of course totally

wrong assumption, because one could use an interface in both

cases which in turn can be both implemented in a class, which is

then both IS-A case.

I will love to read any other deduction like this :)

Many thanks,

Adrian

AdrianSosialuka at 2007-7-12 15:11:46 > top of Java-index,Core,Core APIs...