java - Method chaining + inheritance don’t play well together? -
this question has been asked in c++ context i'm curious java. concerns virtual methods don't apply (i think), if have situation:
abstract class pet { private string name; public pet setname(string name) { this.name = name; return this; } } class cat extends pet { public cat catchmice() { system.out.println("i caught mouse!"); return this; } } class dog extends pet { public dog catchfrisbee() { system.out.println("i caught frisbee!"); return this; } } class bird extends pet { public bird layegg() { ... return this; } } { cat c = new cat(); c.setname("morris").catchmice(); // error! setname returns pet, not cat dog d = new dog(); d.setname("snoopy").catchfrisbee(); // error! setname returns pet, not dog bird b = new bird(); b.setname("tweety").layegg(); // error! setname returns pet, not bird }
in sort of class hierarchy, there way return this
in way doesn't (effectively) upcast the object type?
if want avoid unchecked cast warnings compiler (and don't want @suppresswarnings("unchecked")), need little more:
first of all, definition of pet must self-referential, because pet generic type:
abstract class pet <t extends pet<t>>
secondly, (t) this
cast in setname unchecked. avoid this, use "getthis" technique in excellent generics faq angelika langer:
the "getthis" trick provides way recover exact type of reference.
this results in code below, compiles , runs without warnings. if want extend subclasses, technique still holds (though you'll need genericise intermediate classes).
the resulting code is:
public class testclass { static abstract class pet <t extends pet<t>> { private string name; protected abstract t getthis(); public t setname(string name) { this.name = name; return getthis(); } } static class cat extends pet<cat> { @override protected cat getthis() { return this; } public cat catchmice() { system.out.println("i caught mouse!"); return getthis(); } } static class dog extends pet<dog> { @override protected dog getthis() { return this; } public dog catchfrisbee() { system.out.println("i caught frisbee!"); return getthis(); } } public static void main(string[] args) { cat c = new cat(); c.setname("morris").catchmice(); dog d = new dog(); d.setname("snoopy").catchfrisbee(); } }
Comments
Post a Comment