(Solved) Make a method return the instance that overrides this class

I got an abstract class, and in it there is a method that returns “this”, so I can call multiple statements behind eachother in 1 line (like JME Vectors). Anyway, since it’s abstract it has to be overridden, but when I return “this”, I can’t call the overriding’s class methods, I call the methods from the abstract class.

Does anyone knows how to make this work?



Code for some clarity:



Abstract class methods

[java] public MyAbstractClass doSomething()

{

return this;

}



public Object getValue()

{

return value;

}[/java]



Overriding class

[java] @Override

public String getValue()

{

return (String) super.getValue();

}[/java]



Call from outside

[java] public String getInstanceValue()

{

return instance.doSomething().getValue(); // wont work, incompatible types (wants String, returns Object)



instance.doSomething();

return instance.getValue(); // works

}

[/java]

In the overiding class, just change the doSomething() in the overriding class to return the type of the Overriding class, and not the abstract class.





[java]public abstract classs AbstractClass {

public AbstractClass doSomething() {

return this;

}

}



public class TheClass extends AbstractClass {

public TheClass doSomething() {

return this;

}

}



public class OtherClass extends AbstractClass {

public OtherClass doSomething() {

return (OtherClass) super.doSomething();

}

}[/java]

Ah, thanks, altho doSomething is suppose to do something too, but your code showed me the answer:



In the overriding class it should have

[java]public TheClass doSomething()

{

super.doSomething();

return this;

}[/java]

Please read: http://docs.oracle.com/javase/tutorial/java/javaOO/methods.html



[java]public Object getValue()

public String getValue()

[/java]



These are two different methods, this is almost abusing inheritance and the type system, it just works because you use Object in the super class. This is not so good practice. If you override a method it must have the exact same type signature.

@jmaasing said:
Please read: http://docs.oracle.com/javase/tutorial/java/javaOO/methods.html

[java]public Object getValue()
public String getValue()
[/java]

These are two different methods, this is almost abusing inheritance and the type system, it just works because you use Object in the super class. This is not so good practice. If you override a method it must have the exact same type signature.


I'm sorry, but please, don't do dogmas. It can be usefull, but it often means a bad design. Just don't forget it may be usefull, really usefull.

Java added covariant return types in JDK 5… mostly to make generics work. So subclasses can override methods and have different return types as long as they are a subclass of the parent’s return type.



It’s a valid idiom but it’s usually abusive when the super class returns Object but the subtype returns some specific type. clone() is an example where this works well as an idiom.



To the OP, I’m curious what you are actually doing without the obfuscated-for-our-benefit MyAbstractClass, ie: what is the specific use-case?. Usually when a developer is trying to do this and doesn’t already understand how to do it then they are doing something wrong design-wise.

1 Like
@shirkit said:
I'm sorry, but please, don't do dogmas. It can be usefull, but it often means a bad design. Just don't forget it may be usefull, really usefull.

Yes, sorry about sounding dogmatic. pspeed said it better than me.

To avoid the overrides (especially annoying if you have a lot of them) you could do



[java]class MyAbstractClass<T extends MyAbstractClass> {



T doSomething() {

return (T)this;

}

}

[/java]



Then your subclass just has



[java]class ConcreteClass extends MyAbstractClass<ConcreteClass> {

}

[/java]

No need to override.





I’ve not tried it but I think it should work unless the compiler chokes on the circular reference in the class definition.

@zarch said:
To avoid the overrides (especially annoying if you have a lot of them) you could do

[java]class MyAbstractClass&lt;T extends MyAbstractClass&gt; {

T doSomething() {
return (T)this;
}
}
[/java]

Then your subclass just has

[java]class ConcreteClass extends MyAbstractClass&lt;ConcreteClass&gt; {
}
[/java]
No need to override.


I've not tried it but I think it should work unless the compiler chokes on the circular reference in the class definition.


And still I say if you find yourself needing this then there is a 99% chance that the design is broken.
1 Like
@pspeed said:
And still I say if you find yourself needing this then there is a 99% chance that the design is broken.


I have to agree that it's a high chance, but as I use this on 2 methods on my classes, clone and a custom one, I don't forget about that 1% ^^
@shirkit said:
I have to agree that it's a high chance, but as I use this on 2 methods on my classes, clone and a custom one, I don't forget about that 1% ^^


Yeah, it's one of those things, though: a) there is always another way, and the clincher, b) when you know what that 1% is then you will already know how to employ it properly.

There is a whole pool of advice I give that follows the form:
"Never do X" with a parenthetical remark "(unless you get to the skill level where you can argue with me about it properly)".