[3739] in java-interest
Re: Fundamental flaw in Java library distribution scheme
daemon@ATHENA.MIT.EDU (Jim.Graham@Eng.Sun.COM)
Fri Nov 24 21:12:26 1995
Date: Fri, 24 Nov 1995 16:27:17 -0800
To: java-interest@java.Eng.Sun.COM, david@longview.com
Cc: flar@bendenweyr.Eng.Sun.COM, wnj@sw.central.Sun.COM
From: Jim.Graham@Eng.Sun.COM
Hi Dave,
You keep claiming to have an overriding case and an overloading case to
this problem, whereas what you are really trying to make is a case
about how return types would cause a method override to fail and
another case about how a different argument type would cause a method
override to fail. When you change an argument type you are not
overriding but overloading and you cannot expect the new method to
automatically override calls to the original method. Read further for
more detail:
> 2) for some reason, you are persistently misunderstanding my statement
> of the second form of the problem. You seem to think I am confusing
> overrides and overloads; nothing could be further from the truth.
> If you read every posting/correspondence I have made on this issue
> carefully, I very clearly refer to the second form of the problem
> as having to do with overloading, NOT overriding. So there is
> no disagreement there.
I was basing my discussion on your specific example which you sent out
to show the overloading form of the problem (that example may not have
gone out on the mailing list or newsgroup, but appeared in private mail
to Bill Joy and I).
Specifically:
> From david@longview.com Sat Nov 18 12:40 PST 1995
> Suppose I distribute a library containing a class C that inherits
> the following method from Object:
>
> public boolean equals(Object obj) { ... }
>
> Now, look at a client library L that contains the following compiled code
> somewhere:
>
> C c1, c2;
> boolean same;
>
> ...
> same = c1.equals(c2);
>
> This is fine so far. Now suppose C is changed to overload equals() to
> implement a more specific equality test applicable only if the argument
> is also a C:
>
> public boolean equals(C obj) { ... }
>
> This is perfectly legal overloading, and is unambiguous according to section
> 9.7. Then I distribute my new version of class C. Library L will now be
> violating the language semantics, since the code above will still invoke
> the version of equals from Object, whereas the overloading rules say it
> should invoke my new version of equals, since it is the most specific one
> applicable.
I agree that this is perfectly legal "overloading". The problem is that
you fail to understand what "overloading" means. Since you have overloaded
the equals method, you have created a choice between two separate and
distinct versions of this now polymorphic method. The calling object is
now given a choice between which of the two methods it will call by the
types of the arguments it supplies. This choice is solidified at compile
time as spelled out in section 6.4.8.
You then go on to claim that what you really want is to have calls to
the old inherited equals method that was visible in C be automatically
dispatched to the new overloaded equals method newly implemented in the
C class. This is to say that you want the new C.equals to *override*
the old Object.equals method. As I have already explained, to override
a method you must duplicate the exact signature of the method you are
overriding or you will fail to override and instead you will overload.
If you really want to override the Object.equals method in your C
objects then you will have to implement a method with the signature:
public boolean equals(Object obj)
and decide at run-time if the obj argument is actually an object of
class C and perform your appropriate "more specific equality test".
Please reread the spec (sections 6.4.8 and 6.4.9) for a clarification
of the difference between overloading and overriding (its not exactly
spelled out, but implied by the descriptions).
> The essence of your response to the second problem seems to be
> "this behavior is intentional, and is spelled out in the language
> spec." Of course, Sun can define the language behavior anyway it
> wants; if you want this behavior in the language, so be it.
Yes, this is the intentional behavior of the language.
> Nonetheless, my major point is still true, *regardless* of what
> the language spec says. Here is why: you are saying that the
> language spec intentionally has built into it rules that make the
> behavior of a .class file dependent on when it was compiled. This
> means that the semantics of a Java program is explicitly dependent
> on information that is NOT ENCODED IN THE SOURCE CODE.
If you want to override a method, which is clearly what you want
to do from your above example, then you had better know the existing
method inside and out. If you don't, then you have no business
providing an alternate implementation of that method (which is what
overriding is). If you know it that well, then you surely know its
method signature (i.e. the exact types of its arguments and return
type). If you know its method signature, you should have no problem
overriding it.
> In other words, you are saying that the source code for a Java program
> is not sufficient describe the behavior of that program; you also have
> to know when (and in what environment) each compilation unit was
> last compiled. That is an *extremely* undesirable property. My final
> point follows directly from the above: If a programmer wants to ensure
> that the behavior of his program is dependent only on the current state
> of his source code, he will have to recompile dependent compilation units,
> using a makefile or other mechanism.
This is not true. The necessary burden is that if a programmer wants
to override a method, then he must use its exact same signature in his
subclass. This requires no more knowledge about the compilation
environment than anyone should have if they intend to try and override
a method.
...jim
-
This message was sent to the java-interest mailing list
Info: send 'help' to java-interest-request@java.sun.com