I have a set of classes that are used to store data for which I am currently trying to implement a deep copy mechanism. For this, I would like to define a method deepCopy()
in my abstract class which every extending class needs to implement.
I am struggling with defining the abstract method in a generic way so that every deepCopy()
returns an Object of the class it was implemented in.
public abstract class Foo {
public abstract Foo deepCopy();
}
public class Bar extends Data {
@Override
public Bar deepCopy() {
//copying;
}
}
This is what I want to achieve, but I end up with this:
public abstract class Foo {
public abstract Foo deepCopy();
}
public class Bar extends Data {
@Override
public Foo deepCopy() {
//copying;
}
}
This causes an error when calling deepCopy()
:
public SomeClass extends Foo {
private Bar value;
private SomeClass(final SomeClass original) {
this.value = original.deepCopy(); // type-mismatch since deepCopy returns Foo but value is Bar.
}
@Override
public Foo deepCopy() {
return new SomeClass(this);
}
}
The simplest way to resolve this would be to cast the returned object of deepCopy to Bar, but this seems wrong.
Is there a clean way to achieve this?
You can do this with Generics in java.
Implement the class like this.
public abstract class Foo<Item> {
public abstract Item deepCopy();
}
You can read about generics here http://docs.oracle.com/javase/tutorial/java/generics/
It would seem that covariant return types would solve the issue here:
public abstract class Foo {
public abstract Foo deepCopy();
}
Then Bar
can return a Bar
from the method:
public class Bar extends Foo {
@Override
public Bar deepCopy() {
//copying;
}
}
So:
final Bar bar = new Bar();
final Bar barCopy = bar.deepCopy(); // <- Bar's deepcopy returns a Bar
final Foo foo = ((Foo) bar).deepCopy(); // <- Foo's deepcopy returns a Foo
The is allowed because as Bar extends Foo
you can use a Bar
wherever you would be allowed to use a Foo
. So a subclass can override methods from a superclass that return covariant types.
This would work in the more general case:
public abstract class Foo {
public abstract Number getThing();
}
public class Bar extends Foo {
@Override
public Integer getThing() {
//copying;
}
}
As you can see, Bar.getThing
returns an Integer
but it overrides the method Foo.getThing
which returns a Number
. This is fine because we can use Integer
wherever we can use Number
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.