How to refer to "this" in abstract Java class? - java

Is it possible in Java to use this inside a method of an abstract class, but as an instance of the subclass at hand, not just of the abstract class?
abstract class MyAbstractClass <MyImplementingClass extends MyAbstractClass> {
public abstract MyImplementingClass self();
}
which I overwrite in every subclass I with
class MyImplementingClass extends MyAbstractClass<MyImplementingClass> {
#Override public MyImplementingClass self() {
return this;
}
}
but I wonder if there are more elegant methods to do this. In particular, one that doesn't require every subclass to overwrite a routine like self().

The issue here I believe is that your self() method returns MyImplementingClass and not MyAbstractClass.
You should return a MyAbstractClass, the dynamic type of the returned object will be the relevant one.
I also do not follow why wouldn't you just use this? It returns the object itself, with the correct dynamic type, regardless of where it is called. You can cast it if you need to

When overriding methods in Java, you can override the return type to be a subclass of the original type. This code is completely valid:
abstract class MyAbstractClass {
public MyAbstractClass self() {
return this;
}
}
And the concrete class:
class MyImplementingClass extends MyAbstractClass {
#Override
public MyImplementingClass self() {
return this;
}
}
This is also why you can override clone() to return an exact type instead of just Object:
public class SomeCloneable implements Cloneable {
#Override
public SomeCloneable clone() {
return new SomeCloneable();
}
}

I believe, you can return newInstance() of a class to behave like that
#Override public MyImplementingClass self() {
return MyImplementingClass.newInstance();
}

Related

Overriding method that returns and consumes a generic class with sub-interfaces

I want to make a generic interface that has two abstract methods, and one of them returns and consumes sub-type with same generic type of the interface.
The goal I want to achieve is that creating #FunctionalInterfaces having same parents, but different way of composing themselves.
My first approach is as below,
public interface ParentFunction<T, C extends ParentFunction> {
void doSomething(T t);
C<T> compose(C<T> other);
}
#FunctionalInterface
public interface SonFunction<T> extends ParentFunction<T, SonFunction> {
#Override
default SonFunction<T> compose(SonFunction<T> other){
return null;
}
}
#FunctionalInterface
public interface SonFunction<T> extends ParentFunction<T, SonFunction> {
#Override
default DaughterFunction<T> compose(SonFunction<T> other){
return null;
}
}
But an compile error occurs at C<T> of parent method saying, 'Type "C" does not have type parameters,' and another at #Override of child default method.
I can just separate my child interfaces without extending, but I hope them to have an super-type that the client code will only knows.
Is there any cool technique that I may use to achieve it?
In Java, you cannot do C<T>, however, you can require C to extend ParentFunction<T,C>
Same applies to your SonFunction and DaughterFunction.
Try this:
public interface ParentFunction<T, C extends ParentFunction<T, C>> {
void doSomething(T t);
C compose(C other);
}
#FunctionalInterface
public interface SonFunction<T> extends ParentFunction<T, SonFunction<T>> {
#Override
default SonFunction<T> compose(SonFunction<T> other){
return null;
}
}
#FunctionalInterface
public interface DaughterFunction<T> extends ParentFunction<T, DaughterFunction<T>> {
#Override
default DaughterFunction<T> compose(DaughterFunction<T> other){
return null;
}
}

Java: Cannot override abstract method passing subclass [duplicate]

This question already has an answer here:
Is it possible to override a superclass' method with a parameter extending the superclass' method parameter?
(1 answer)
Closed 6 years ago.
I have an abstract class
public abstract class SuperclassA{
public abstract void method(SuperclassB b);
}
And an implementation
public class SubclassA extends SuperclassA{
#override
public void method(SubclassB b){
}
}
where SubclassB extends SuperclassB.
My NetBeans editor complains that I am not overriding method.
What can I do to actually pass a subclass to method?
In order to override a method of the base class, the sub-class's method must have the same signature.
If you want the overridden method to accept only instances of SubclassB, you can test for it :
public class SubclassA extends SuperclassA
{
#Override
public void method(SuperclassB b){
if (!(b instanceof SubclassB)) {
// throw some exception
}
SubclassB sb = (SubclassB) b;
...
}
}
You can call that method as follows :
SuperclassA a = new SubclassA ();
a.method (new SubclassB ());
Think of the method signatures of a class or interface as a contract or a promise of what it and any subclass can do.
SuperclassA promises to do action method for any SuperclassB. In order for SubclassA to be a SuperclassA it must do action method for all SuperclassB. The issue is that it only does action method for some types of SuperclassB.
Here is the same situation with names that are easier to understand.
abstract class Pet {
// Pet methods
}
class Cat extends Pet {
// Cat methods
}
class Dog extends Pet {
// Dog methods
}
abstract class PetShop {
public abstract void groom(Pet pet);
}
The Pet shop class promises that any PetShop can groom any Pet, including dogs.
PetShop shop = new FranksPetShop();
shop.groom(new Dog());
If we define FranksPetShop like so it only defines how to groom Cat's, any other type of Pet (including dogs) is not defined.
class FranksPetShop {
#Override
public abstract void groom(Cat cat) {
// Groom that cat
}
}
To solve this FranksPetShop has to define how to groom a Pet not just a Cat.
class FranksPetShop {
#Override
public abstract void groom(Pet pet) {
// Groom that pet
}
}
Actual, Method Signature is,
public abstract void method(SuperclassB b);// into abstract class
Your overrided Method Signature must be same, Otherwise it's not
override, in fact it will be treated like overloading,
#override
public void method(SuperclassB b){
}
//OverLoad not Override
public void method(SubclassB b){
}
The method in SubclassA takes in a type of SubclassB. The method in SuperclassA is taking in a type of SuperclassB. You are not overriding the parent class method, you are overloading by using a different type.
Depending on what you are trying to accomplish, you could try this
public class SubclassA extends SuperclassA{
#override
public void method(SuperclassB b){
}
}
Which would override the method you want. As long as SubclassB is a child of SuperclassB, then you will still be able to pass SubclassB in.
You can still have an overloaded method that takes in Subclasss if you want.
public class SubclassA extends SuperclassA{
#override
public void method(SuperclassB b){
}
public void method(SubclassB b){
}
}
Take a look at this thread for more info about overloading vs overriding.
Refer to oracle documentation page on override.
An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method.
The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed.
The overriding method has the same name, number and type of parameters, and return type as the method that it override
In your case, you did not use same method signature.
public void method(SubclassB b){
should be changed to
public void method(SuperclassB b){
Now you can use workaround suggested by Eran by using instanceof

Object of a subclass in a variable of type interface (implemente by superclass) calls superclass method?

I have an interface, a superclass that implements it, and a subclass that extends the superclass. Then I have test that creates an object of the type of the subclass, but stores it in a variable of the type of the interface. When I use a method that is defined in the interface, implemented in the superclass, and overridden in the subclass, it calls the method from the superclass. Why is this? I can't change the test class, but did I do something wrong with the subclass?
public interface SampleInterface<T extends Comparable<T>>{
void add(T element);
//other methods, etc
}
public class SampleClassA<T extends Comparable<T>> implements SampleInterface<T> {
public void add(){
System.out.println("super");
}
}
#Override
public class SampleClassB<T extends Comparable<T>> extends SampleClassA<T> {
public void add(){
System.out.println("sub");
}
}
Then I want to use the code in a test that looks like this:
private SampleInterface<Integer> test = new SampleClassB<Integer>();
test.add();
And it prints "super", but I want "sub". This is a simplified version of my code, also.

Method declaration in superclass

I wan't to make a method declaration in a superclass called 'dataItem' so that all subclasses that implement that method must have a return type that is of that implementing class. Is that possible?
For example if I have class 'Experiment' which implements 'dataItem' and I have method newItem() . Which for 'Experiment' should only be able to return 'Experiment' datatype and not any other implementation of 'dataItem'.
You can't force a class method to return the type it is a member of. You have to actually specify it.
public class DataItem {
public DataItem getItem() {return null;}
}
public class Experiment extends DataItem {
#Override
public Experiment getItem() {return null;}
}
This works because Experiment is a sub class of DataItem and can therefore be used anywhere a DataItem could be used.
I suppose you're looking for this:
public interface dataitem<T>
{
public T newItem();
};
public class Element implements dataitem<Element>
{
#Override
public Element newItem()
{
return new Element();
}
}

Is it possible declare and implement a method once, but vary the return type to match subinterfaces in a robust manner?

First off, I want to say there is no use case for this. The only thing I am trying to do is explore if this is possible.
What I am trying to do is "rebrand" the return signature of a method in the base interface to that of a child interface.
The goal: declare and implement a method once, but vary the return type to match subinterfaces. I have figured out how to achieve this in some cases, but it breaks down in certain situations.
Imagine if I have base interface B and it has a method B doWork(). Also, there is an implementation of B that implements doWork(). Due to the nature of doWork(), this implementation should be the only one that exists.
Now, this is pretty easy to do with Generics. For the above example:
interface B<T extends B> {
T doWork();
}
class BImpl<T extends B> implements B<T> {
#Override
public T doWork() { return something; }
}
And the child interface/impl would look like this maybe:
interface C extends B<C> {
void somethingCSpecific();
}
class CImpl extends BImpl<C> implements C {
#Override
public void somethingCSpecific() { }
}
Anyone constructing CImpl would see that doWork() returns a C.
C obj = new CImpl().doWork() // The money shot. No casting needed.
And here is where it breaks down... Imagine B now looks like this:
public interface B<T extends B> {
T thisOrThat(T that);
boolean something();
}
And I want to do this in BImpl:
class BImpl<T extends B> implements B<T> {
#Override
public T thisOrThat(T that) {
if (that.something())
return that;
return this; // Error!! _this_ might be a different T than _that_.
}
#Override
public boolean something() { return whatever; }
}
Note where the error happens.
Obviously, this can't work without an unsafe and dubious cast. But if I knew that the implementation of this in the above thisOrThat method was the same as the implementation of that, everything would be ok.
So, to my question. Is there a way to restrict this and that to the same type, without knowing that type a priori?
Or maybe is there a different way to go about doing this, but having the same result? Namely only having to declare AND implement thisOrThat() just once, yet have the return type adapt to the subinterface?
Thanks.
Make your class BImpl abstract and add a view method to it which is implemented by the specific classes extending your abstract base class:
public abstract class BImpl<T extends B<T>> implements B<T> {
#Override
public T thisOrThat(T that) {
if (that.something())
return that;
return this.asT();
}
#Override
public boolean something() {
// TODO Auto-generated method stub
return false;
}
protected abstract T asT();
}
Every of your classes still needs to implement T asT() then, but this is simple and compiles without warning:
public class C extends BImpl<C> implements B<C> {
#Override
protected C asT() {
return this;
}
}
If I understand your problem correctly, then the way to solve it is with a sort of self-referential generic: B<T extends B<T>>.
I think what you want is class BImpl implements B<BImpl>, in which case everything type checks normally.

Categories