Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #36809 > unrolled thread
| Started by | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| First post | 2017-07-07 06:10 -0700 |
| Last post | 2017-07-07 17:43 -0400 |
| Articles | 12 — 2 participants |
Back to article view | Back to comp.lang.java.programmer
Confusing interface Eric Douglas <e.d.programmer@gmail.com> - 2017-07-07 06:10 -0700
Re: Confusing interface Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-07-07 09:45 -0400
Re: Confusing interface Eric Douglas <e.d.programmer@gmail.com> - 2017-07-07 07:37 -0700
Re: Confusing interface Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-07-07 11:26 -0400
Re: Confusing interface Eric Douglas <e.d.programmer@gmail.com> - 2017-07-07 11:24 -0700
Re: Confusing interface Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-07-07 14:50 -0400
Re: Confusing interface Eric Douglas <e.d.programmer@gmail.com> - 2017-07-07 12:00 -0700
Re: Confusing interface Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-07-07 15:27 -0400
Re: Confusing interface Eric Douglas <e.d.programmer@gmail.com> - 2017-07-07 12:47 -0700
Re: Confusing interface Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-07-07 16:25 -0400
Re: Confusing interface Eric Douglas <e.d.programmer@gmail.com> - 2017-07-07 13:39 -0700
Re: Confusing interface Eric Sosman <esosman@comcast-dot-net.invalid> - 2017-07-07 17:43 -0400
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-07-07 06:10 -0700 |
| Subject | Confusing interface |
| Message-ID | <cd610d1e-ecc4-443b-b346-eb8847b22b74@googlegroups.com> |
Oracle defines this
public interface TreeNode
which contains this
TreeNode getParent();
Then they define this
public interface MutableTreeNode extends TreeNode
which contains this
void setParent(MutableTreeNode newParent);
Then they define this
public class DefaultMutableTreeNode implements Cloneable,
MutableTreeNode, Serializable
which contains this
@Transient
public void setParent(MutableTreeNode newParent) {
public TreeNode getParent() {
Now I define
public class MyCustomTreeNode extends DefaultMutableTreeNode
and Eclipse allows
@Override
public MyCustomTreeNode getParent()
but I must keep the signature
public void setParent(MutableTreeNode newParent)
If I put @Override on the set and declare the parameter as MyCustomTreeNode, it says must override or implement a supertype method.
If the get and set are both using interface parameters, and my custom class is simply extending a class which implements one interface which extends the other, why is one allowed and not the other?
[toc] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2017-07-07 09:45 -0400 |
| Message-ID | <ojo339$fa$1@dont-email.me> |
| In reply to | #36809 |
On 7/7/2017 9:10 AM, Eric Douglas wrote:
> Oracle defines this
> public interface TreeNode
>
> which contains this
> TreeNode getParent();
>
> Then they define this
> public interface MutableTreeNode extends TreeNode
>
> which contains this
> void setParent(MutableTreeNode newParent);
>
> Then they define this
> public class DefaultMutableTreeNode implements Cloneable,
> MutableTreeNode, Serializable
>
> which contains this
> @Transient
> public void setParent(MutableTreeNode newParent) {
>
> public TreeNode getParent() {
>
> Now I define
> public class MyCustomTreeNode extends DefaultMutableTreeNode
>
> and Eclipse allows
> @Override
> public MyCustomTreeNode getParent()
>
> but I must keep the signature
> public void setParent(MutableTreeNode newParent)
>
> If I put @Override on the set and declare the parameter as MyCustomTreeNode, it says must override or implement a supertype method.
> If the get and set are both using interface parameters, and my custom class is simply extending a class which implements one interface which extends the other, why is one allowed and not the other?
Because `setParent(MyCustomTreeNode newParent)' does not override
the setParent() method of the superclass. You can write the method
with the signature you like, but it's not an override. Consider:
MyCustomTreeNode parent = ...;
MyCustomTreeNode child = ...;
child.setParent(parent);
So far, all is well and behaves as you intend. Next, however:
DefaultMutableTreeNode kidnapper = ...;
child.setParent(kidnapper);
Question: Which setParent() method runs, the one in your class or the
one in the superclass? Right you are, it's the superclass' method --
which means your class has not overridden it.
I imagine many people encounter this same confusion -- I confess
that I did, too, many years ago. I implemented
class MyMap extends AbstractMap<Thing,Wotsit>
... and provided the method
Wotsit get(Thing key)
To my surprise, some calls to get() went directly to the get() of
AbstractMap and not to my code! I had made the same mistake then
that you are making now. (My error was before @Override came onto
the scene, so the compiler didn't alert me. Be thankful that the
tools have improved so you're faced with a compile error instead of
with a baffling mystery.)
--
esosman@comcast-dot-net.invalid
Twelve hundred ninety-three days to go.
[toc] | [prev] | [next] | [standalone]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-07-07 07:37 -0700 |
| Message-ID | <0175016c-5ab9-4867-a9d1-7c43907e4427@googlegroups.com> |
| In reply to | #36811 |
On Friday, July 7, 2017 at 9:46:10 AM UTC-4, Eric Sosman wrote:
> Because `setParent(MyCustomTreeNode newParent)' does not override
> the setParent() method of the superclass. You can write the method
> with the signature you like, but it's not an override. Consider:
>
> MyCustomTreeNode parent = ...;
> MyCustomTreeNode child = ...;
> child.setParent(parent);
>
> So far, all is well and behaves as you intend. Next, however:
>
> DefaultMutableTreeNode kidnapper = ...;
> child.setParent(kidnapper);
>
> Question: Which setParent() method runs, the one in your class or the
> one in the superclass? Right you are, it's the superclass' method --
> which means your class has not overridden it.
>
but the setParent method in DefaultMutableTreeNode accepts a MutableTreeNode, not a DefaultMutableTreeNode. So I would think if you override that in MyCustomTreeNode to accept a MyCustomTreeNode, then if child is an instance of MyCustomTreeNode, it should throw an error on setParent if the parameter is not an instance of MyCustomTreeNode.
It does sound odd that the get can override the interface with the custom class but the set cannot, so if you want to override it with the custom class you have to manually trap for it.
public void setParent(DefaultMutableTreeNode newParent){
if (!(newParent instanceof MyCustomTreeNode)) {throw new IllegalArgumentException("This class requires a custom node")}
If you override the get without overriding and trapping the set, they can put in an invalid super class instance that will crash the get.
> I imagine many people encounter this same confusion -- I confess
> that I did, too, many years ago. I implemented
>
> class MyMap extends AbstractMap<Thing,Wotsit>
>
> ... and provided the method
>
> Wotsit get(Thing key)
>
I can't imagine there's many instances where you want to override without overriding, to have the same method signature but extend the parameter, so if they pass in your class instance it goes to your method, if they pass in an instance of it's super class/interface it goes to the super method.
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2017-07-07 11:26 -0400 |
| Message-ID | <ojo90v$l5f$1@dont-email.me> |
| In reply to | #36812 |
On 7/7/2017 10:37 AM, Eric Douglas wrote:
> On Friday, July 7, 2017 at 9:46:10 AM UTC-4, Eric Sosman wrote:
>> Because `setParent(MyCustomTreeNode newParent)' does not override
>> the setParent() method of the superclass. You can write the method
>> with the signature you like, but it's not an override. Consider:
>>
>> MyCustomTreeNode parent = ...;
>> MyCustomTreeNode child = ...;
>> child.setParent(parent);
>>
>> So far, all is well and behaves as you intend. Next, however:
>>
>> DefaultMutableTreeNode kidnapper = ...;
>> child.setParent(kidnapper);
>>
>> Question: Which setParent() method runs, the one in your class or the
>> one in the superclass? Right you are, it's the superclass' method --
>> which means your class has not overridden it.
>>
>
> but the setParent method in DefaultMutableTreeNode accepts a MutableTreeNode, not a DefaultMutableTreeNode. So I would think if you override that in MyCustomTreeNode to accept a MyCustomTreeNode, then if child is an instance of MyCustomTreeNode, it should throw an error on setParent if the parameter is not an instance of MyCustomTreeNode.
Yes, DefaultMutableTreeNode::setParent accepts a MutableTreeNode.
*Any* MutableTreeNode, including a DefaultMutableTreeNode or a
MyCustomTreeNode or a FoundItSomewhereOnStackOverflowTreeNode or ...
Your non-overriding method accepts only a MyCustomTreeNode, not
any of the others.
Here's a pared-down version that avoids the complications of
interfaces and Swing; try it and see if you understand what's afoot:
class Super {
void doIt(Super s) {
System.out.println("Super::doIt");
}
}
class Sub extends Super {
void doIt(Sub s) {
System.out.println("Sub::doIt");
}
}
class Driver {
public static void main(String[] unused) {
Super sup = new Super();
sup.doIt(sup); // no surprises yet
Sub sub = new Sub();
sub.doIt(sub); // no surprises yet
sub.doIt(sup); // surprised?
sub.doIt((Super) sub); // how about now?
}
}
--
esosman@comcast-dot-net.invalid
Twelve hundred ninety-three days to go.
[toc] | [prev] | [next] | [standalone]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-07-07 11:24 -0700 |
| Message-ID | <c30448c3-8f2b-4eba-80c4-c395566dd970@googlegroups.com> |
| In reply to | #36814 |
On Friday, July 7, 2017 at 11:27:19 AM UTC-4, Eric Sosman wrote:
> Here's a pared-down version that avoids the complications of
> interfaces and Swing; try it and see if you understand what's afoot:
>
> class Super {
> void doIt(Super s) {
> System.out.println("Super::doIt");
> }
> }
>
> class Sub extends Super {
> void doIt(Sub s) {
> System.out.println("Sub::doIt");
> }
> }
>
> class Driver {
> public static void main(String[] unused) {
> Super sup = new Super();
> sup.doIt(sup); // no surprises yet
> Sub sub = new Sub();
> sub.doIt(sub); // no surprises yet
> sub.doIt(sup); // surprised?
> sub.doIt((Super) sub); // how about now?
> }
> }
>
So wait, if class A implements Cloneable and class B extends A and does not implement Cloneable, is class B cloneable? Does cloning instance of B give you an instance of A?
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2017-07-07 14:50 -0400 |
| Message-ID | <ojokuh$tqh$1@dont-email.me> |
| In reply to | #36820 |
On 7/7/2017 2:24 PM, Eric Douglas wrote:
> On Friday, July 7, 2017 at 11:27:19 AM UTC-4, Eric Sosman wrote:
>> Here's a pared-down version that avoids the complications of
>> interfaces and Swing; try it and see if you understand what's afoot:
>>
>> class Super {
>> void doIt(Super s) {
>> System.out.println("Super::doIt");
>> }
>> }
>>
>> class Sub extends Super {
>> void doIt(Sub s) {
>> System.out.println("Sub::doIt");
>> }
>> }
>>
>> class Driver {
>> public static void main(String[] unused) {
>> Super sup = new Super();
>> sup.doIt(sup); // no surprises yet
>> Sub sub = new Sub();
>> sub.doIt(sub); // no surprises yet
>> sub.doIt(sup); // surprised?
>> sub.doIt((Super) sub); // how about now?
>> }
>> }
>>
>
> So wait, if class A implements Cloneable and class B extends A and does not implement Cloneable, is class B cloneable? Does cloning instance of B give you an instance of A?
B implements Cloneable. A subclass implements all interfaces
implemented by its superclass(es), and possibly more that it adds
of its own volition.
Cloning a B gives whatever A's clone() implementation returns.
That might be a B, or an A, or a C, or an Object -- it's entirely
up to clone().
... but what has any of this to do with overriding or failing
to override? Did you work through the example I gave? Did it
behave as you expected (and/or did your expectations adjust to
its behavior)?
Overriding is "Java 101" stuff. It's probably not covered in
Chapter One or in the first class meeting, but certainly arises
by the time you get to Chapter Five or the tenth meeting. Have
you, perhaps, fast-forwarded a little too freely? It might be a
good idea to re-read your textbook, including the early chapters.
Maybe some things that eluded your attention the first time through
will make sense now that you have more context.
--
esosman@comcast-dot-net.invalid
Twelve hundred ninety-three days to go.
[toc] | [prev] | [next] | [standalone]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-07-07 12:00 -0700 |
| Message-ID | <ad49ff16-7feb-46d7-82df-d13b22d69a90@googlegroups.com> |
| In reply to | #36821 |
On Friday, July 7, 2017 at 2:50:49 PM UTC-4, Eric Sosman wrote: > Cloning a B gives whatever A's clone() implementation returns. > That might be a B, or an A, or a C, or an Object -- it's entirely > up to clone(). > > ... but what has any of this to do with overriding or failing > to override? Did you work through the example I gave? Did it > behave as you expected (and/or did your expectations adjust to > its behavior)? > That is the override, or lack of, and it sounds like you're saying what I suspect. DefaultMutableTreeNode implements Cloneable, so if I extend it I must implement Cloneable, or else create a clone() method that simply throws an exception. Otherwise someone could clone my class and get an instance of DefaultMutableTreeNode, when they should expect it to return an instance of the extending class.
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2017-07-07 15:27 -0400 |
| Message-ID | <ojon3m$5ff$1@dont-email.me> |
| In reply to | #36823 |
On 7/7/2017 3:00 PM, Eric Douglas wrote:
> On Friday, July 7, 2017 at 2:50:49 PM UTC-4, Eric Sosman wrote:
>> Cloning a B gives whatever A's clone() implementation returns.
>> That might be a B, or an A, or a C, or an Object -- it's entirely
>> up to clone().
>>
>> ... but what has any of this to do with overriding or failing
>> to override? Did you work through the example I gave? Did it
>> behave as you expected (and/or did your expectations adjust to
>> its behavior)?
>>
>
> That is the override, or lack of, and it sounds like you're saying what I suspect.
> DefaultMutableTreeNode implements Cloneable, so if I extend it I must implement Cloneable, or else create a clone() method that simply throws an exception. Otherwise someone could clone my class and get an instance of DefaultMutableTreeNode, when they should expect it to return an instance of the extending class.
"To extend it I must implement Cloneable ..." Simply by extending
you *already* implement Cloneable. If you're happy with the clone()
implementation in the superclass, just stay happy and move on to other
matters. If you're unhappy, override.
Observe that the caller of clone() receives an Object reference,
not a DefaultMutableTreeNode or MyCustomTreeNode reference. The
referred-to instance's type is something you'll need to know from
the documentation, or infer by reflection.
But this still has nothing to do with your original question,
which was (boiled down to essentials): "If a superclass has a method
that takes a Thing parameter, why can't I override it with a method
taking a SubclassOfThing parameter?" But you're now trying to pose
the same question about clone() -- and since clone() takes zero count
them zero parameters, the question has no meaning.
--
esosman@comcast-dot-net.invalid
Twelve hundred ninety-three days to go.
[toc] | [prev] | [next] | [standalone]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-07-07 12:47 -0700 |
| Message-ID | <74f526e3-2f48-4e72-a52c-f3b998f61997@googlegroups.com> |
| In reply to | #36824 |
On Friday, July 7, 2017 at 3:27:41 PM UTC-4, Eric Sosman wrote: > But this still has nothing to do with your original question, > which was (boiled down to essentials): "If a superclass has a method > that takes a Thing parameter, why can't I override it with a method > taking a SubclassOfThing parameter?" But you're now trying to pose > the same question about clone() -- and since clone() takes zero count > them zero parameters, the question has no meaning. > Right then, same topic different question. So 1) You can always override the return value of a method with a subclass of that value. 2) If you don't override a public method, that method can be called on your subclass. If that method returns an instance of your super class, the return value will be an instance of your subclass. 3) You cannot override a method parameter with a different class. If you require the super method of your class to only be called from your class with a parameter that is a subclass of what the super class expects, you just check instanceof inside the method.
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2017-07-07 16:25 -0400 |
| Message-ID | <ojoqgk$h33$1@dont-email.me> |
| In reply to | #36825 |
On 7/7/2017 3:47 PM, Eric Douglas wrote:
> On Friday, July 7, 2017 at 3:27:41 PM UTC-4, Eric Sosman wrote:
>> But this still has nothing to do with your original question,
>> which was (boiled down to essentials): "If a superclass has a method
>> that takes a Thing parameter, why can't I override it with a method
>> taking a SubclassOfThing parameter?" But you're now trying to pose
>> the same question about clone() -- and since clone() takes zero count
>> them zero parameters, the question has no meaning.
>>
>
> Right then, same topic different question.
> So
> 1) You can always override the return value of a method with a subclass of that value.
Right. If the overridden method returns a Thing, the overriding
method can return a SubclassOfThing. Why? Because a SubclassOfThing
"is a" Thing, so the overriding method still follows the overridden's
"contract:" it returns some kind of a Thing.
> 2) If you don't override a public method, that method can be called on your subclass. If that method returns an instance of your super class, the return value will be an instance of your subclass.
Wrong, or "not necessarily so." The method returns whatever it
returns. There may be code in the method to snoop out the class of
the `this' on which it was called, and to tailor the nature of the
returned object accordingly. But unless it does something of that
kind, there's no magic that somehow replaces the object returned
with a different object of one of its subclasses.
clone() usually (*usually*) does such tailoring, but that is not
a requirement of the language. If (*if*) clone() returns the object
it obtains from super.clone() and if that is in turn obtained from
super.super.clone() and so on all the way up to Object, then the
object will have the same class as `this'. However, a particular
class is allowed to implement its clone() in some other way, and to
return an object of an "atypical" type.
> 3) You cannot override a method parameter with a different class. If you require the super method of your class to only be called from your class with a parameter that is a subclass of what the super class expects, you just check instanceof inside the method.
That'd be one way. Another would be to write two methods, one
an override and the other an augmentation:
class Super {
void method(Thing thing) { ... }
}
class Sub extends Super {
@Override
void method(Thing thing) {
if (thing instanceof MyThing) // might also allow null
method((MyThing) thing);
else
throw new WrongTypeException();
}
void method(MyThing thing) {
... // might or might not call super.method(thing)
... // and maybe do other things in addition
}
}
This way, a call whose compile-time type is MyThing (or a subclass
thereof) goes directly to the augmenting method without the overhead
of checking, while calls with other compile-time types get screened
for the proper run-time type.
--
esosman@comcast-dot-net.invalid
Twelve hundred ninety-three days to go.
[toc] | [prev] | [next] | [standalone]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-07-07 13:39 -0700 |
| Message-ID | <dbddbf8a-67df-4672-9ba2-f61d273cee9e@googlegroups.com> |
| In reply to | #36828 |
On Friday, July 7, 2017 at 4:25:41 PM UTC-4, Eric Sosman wrote:
> > 2) If you don't override a public method, that method can be called on your subclass. If that method returns an instance of your super class, the return value will be an instance of your subclass.
>
> Wrong, or "not necessarily so." The method returns whatever it
> returns. There may be code in the method to snoop out the class of
> the `this' on which it was called, and to tailor the nature of the
> returned object accordingly. But unless it does something of that
> kind, there's no magic that somehow replaces the object returned
> with a different object of one of its subclasses.
>
> clone() usually (*usually*) does such tailoring, but that is not
> a requirement of the language. If (*if*) clone() returns the object
> it obtains from super.clone() and if that is in turn obtained from
> super.super.clone() and so on all the way up to Object, then the
> object will have the same class as `this'. However, a particular
> class is allowed to implement its clone() in some other way, and to
> return an object of an "atypical" type.
>
Of course it seems wrong but I suppose you could write a clone() method which returns an object other than an instance of the current class.
If you write a clone() method such as they did in the DefaultMutableTreeNode class, and it's called from a subclass of that class which does not override it, it returns an instance of the subclass?
public Object clone() {
DefaultMutableTreeNode newNode;
try {
newNode = (DefaultMutableTreeNode)super.clone();
// shallow copy -- the new node has no parent or children
newNode.children = null;
newNode.parent = null;
} catch (CloneNotSupportedException e) {
// Won't happen because we implement Cloneable
throw new Error(e.toString());
}
return newNode;
}
> > 3) You cannot override a method parameter with a different class. If you require the super method of your class to only be called from your class with a parameter that is a subclass of what the super class expects, you just check instanceof inside the method.
>
> That'd be one way. Another would be to write two methods, one
> an override and the other an augmentation:
>
> class Super {
> void method(Thing thing) { ... }
> }
>
> class Sub extends Super {
> @Override
> void method(Thing thing) {
> if (thing instanceof MyThing) // might also allow null
> method((MyThing) thing);
> else
> throw new WrongTypeException();
> }
>
> void method(MyThing thing) {
> ... // might or might not call super.method(thing)
> ... // and maybe do other things in addition
> }
> }
>
> This way, a call whose compile-time type is MyThing (or a subclass
> thereof) goes directly to the augmenting method without the overhead
> of checking, while calls with other compile-time types get screened
> for the proper run-time type.
>
I see. So it is best to override a parameter with a subclass of the parameter by overriding and killing the parameter. If class A extends class B, your super class passes in an instance of B, and you want the same method to only accept instances of A, first copy the signature to accept A and throw invalid. Then write the signature to accept A, which can call the super method looking for B if you want it to do the same thing. (addCarToLot(Car c), but CarDealerF only wants to allow addCarToLot(Ford c))
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2017-07-07 17:43 -0400 |
| Message-ID | <ojov2k$vsa$1@dont-email.me> |
| In reply to | #36830 |
On 7/7/2017 4:39 PM, Eric Douglas wrote:
> On Friday, July 7, 2017 at 4:25:41 PM UTC-4, Eric Sosman wrote:
>>> 2) If you don't override a public method, that method can be called on your subclass. If that method returns an instance of your super class, the return value will be an instance of your subclass.
>>
>> Wrong, or "not necessarily so." The method returns whatever it
>> returns. There may be code in the method to snoop out the class of
>> the `this' on which it was called, and to tailor the nature of the
>> returned object accordingly. But unless it does something of that
>> kind, there's no magic that somehow replaces the object returned
>> with a different object of one of its subclasses.
>>
>> clone() usually (*usually*) does such tailoring, but that is not
>> a requirement of the language. If (*if*) clone() returns the object
>> it obtains from super.clone() and if that is in turn obtained from
>> super.super.clone() and so on all the way up to Object, then the
>> object will have the same class as `this'. However, a particular
>> class is allowed to implement its clone() in some other way, and to
>> return an object of an "atypical" type.
>>
>
> Of course it seems wrong but I suppose you could write a clone() method which returns an object other than an instance of the current class.
It would be unusual, but you could. Remember, the very notion of
what constitutes a "clone" is class-specific, defined by the class'
own implementation of clone() to reflect its own needs and purposes.
For example, some class somewhere might want to distinguish between
"originals" and "carbon copies" (don't ask me why, but it might):
class Original implements Cloneable {
private Thing thing;
private Wotsit wotsit;
...
@Override
public Object clone() { // or Original, or CarbonCopy
CarbonCopy copy = new CarbonCopy();
copy.thing = thing;
copy.wotsit = wotsit;
...
return copy;
}
...
}
class CarbonCopy extends Original {}
> If you write a clone() method such as they did in the DefaultMutableTreeNode class, and it's called from a subclass of that class which does not override it, it returns an instance of the subclass?
In the 1.8.0_131 implementation, yes: The clone() method follows the
"usual convention" and obtains its new object from super.clone(), which
turns out to be Object::clone, which generates an object whose class is
that of `this'.
The JavaDoc, unfortunately, is silent about whether this behavior is
something you can Rely On Forever. My guess is that you can; although
it's allowed for clone() to return a weird object it's not common, and
quite likely the author of the JavaDoc never thought it necessary to
mention the fact. (A weakness of JavaDoc is that it's written by people
skilled in Java, not by people skilled in expository prose. And the
fact that it's sourced from the code base means you can't give it an
editing pass without going through an entire update-and-regression-test
cycle on the modified code ...)
> I see. So it is best to override a parameter with a subclass of the parameter by overriding and killing the parameter. If class A extends class B, your super class passes in an instance of B, and you want the same method to only accept instances of A, first copy the signature to accept A and throw invalid. Then write the signature to accept A, which can call the super method looking for B if you want it to do the same thing. (addCarToLot(Car c), but CarDealerF only wants to allow addCarToLot(Ford c))
Whether it's "best" ... Well, I don't know. It's probably "best"
from a tactical standpoint, but the strategic question "Is this really
what I want to do?" should be asked -- that is, you should consider
whether you've designed the thing well. Perhaps a redesign could make
the problem go away; in your addCarToLot example I'd ponder whether
generics might be a better approach.
A design in which a mistake simply isn't possible is usually better
than one that applies bullet-proof tactics to catch mistakes.
--
esosman@comcast-dot-net.invalid
Twelve hundred ninety-three days to go.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.java.programmer
csiph-web