Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Eric Sosman Newsgroups: comp.lang.java.programmer Subject: Re: Confusing interface Date: Fri, 7 Jul 2017 17:43:14 -0400 Organization: A noiseless patient Spider Lines: 78 Message-ID: References: <0175016c-5ab9-4867-a9d1-7c43907e4427@googlegroups.com> <74f526e3-2f48-4e72-a52c-f3b998f61997@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Fri, 7 Jul 2017 21:39:32 -0000 (UTC) Injection-Info: mx02.eternal-september.org; posting-host="ce67c2b27e35227899c522f2fd53802e"; logging-data="32650"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+JGDUzi4h5v5jKO5tHSkTo" User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 In-Reply-To: Content-Language: en-US Cancel-Lock: sha1:B1f51qoyTkDDO2FdfdfumlRJUbo= Xref: csiph.com comp.lang.java.programmer:36831 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.