Reputation: 3
Initially I wanted to create a generic way of deep copying objects which implement a 'X' interface. However, I did not want to write a copy list function for every class which implemented 'X'. Instead I created a generic Class which bounds it's generic with interface 'X'.
The problem lies that if class 'A' implements 'X' and contains sub-classes which (do)/(do not) implement 'X'. How do you stop sub-classes from inheriting from the 'A' implementation of 'X' and force their own implementation, without having to implement 'X for every sub-class.
I am pretty sure that this is impossible to do in java, due to inheritance, and generics.
Here is the implementation thus far, but I need a type cast which brings unsafe operations for sub-classes not inheriting interface 'X'.
import java.util.*;
public class HelloWorld {
public static void main(String[] args) {
// Prints "Hello, World" to the terminal window.
System.out.println("Hello, World");
List<Foo> l = new ArrayList<Foo>();
List<Bar> b = new ArrayList<Bar>();
List<Nar> n = new ArrayList<Nar>();
GenericCopyClass<Foo> g = new GenericCopyClass<Foo>();
GenericCopyClass<Bar> gb = new GenericCopyClass<Bar>();
GenericCopyClass<Nar> gn = new GenericCopyClass<Nar>();
l.add(new Foo());
l.add(new Foo());
l.add(new Foo());
b.add(new Bar());
b.add(new Bar());
b.add(new Bar());
n.add(new Nar());
n.add(new Nar());
n.add(new Nar());
//prints FOO
List<Foo> foo = g.copyList(l);
//prints BAR
List<Bar> bar = gb.copyList(b);
//prints FOO
List<Nar> nar = gn.copyList(n);
/* Is there a clean way to prevent a typecast of Foo to Nar using generics*/
}
}
class Foo implements WantToClone{
public Foo(){}
private Foo(int i){
System.out.println("Foo");
}
public Foo instance(){
return new Foo(1);
}
}
class Bar extends Foo{
public Bar(){}
private Bar(int i){
System.out.println("Bar");
}
public Bar instance(){
return new Bar(1);
}
}
class Nar extends Foo{
public Nar(){}
}
interface WantToClone<E extends WantToClone<E>>{
public E instance();
}
class GenericCopyClass<S extends WantToClone>{
public GenericCopyClass(){}
public List<S> copyList(List<S> original){
List<S> temp = new ArrayList<S>();
for(S item : original){
temp.add((S)item.instance());
}
return original;
}
}
The output is as follows:
Hello, World
Foo
Foo
Foo
Bar
Bar
Bar
Foo
Foo
Foo
*edit 1
Problems:
implicit type cast:
temp.add((S)item.instance());
interface does not explicitly specify the class instance:
interface WantToClone<E extends WantToClone<E>>
Upvotes: 0
Views: 2874
Reputation: 5948
I would go with parametrized abstract class that will contain all common method and let sub classes implement only instance
method:
public abstract class AbstractFoo< F extends AbstractFoo<F> >
implements WantToClone<F>{
public AbstractFoo(){}
//add common methods here
}
public class Foo extends AbstractFoo<Foo>{
public Foo(){}
private Foo(int i){
System.out.println("Foo");
}
public Foo instance(){
return new Foo(1);
}
}
public class Bar extends AbstractFoo<Bar>{
public Bar(){}
private Bar(int i){
System.out.println("Bar");
}
public Bar instance(){
return new Bar(1);
}
}
public class Nar extends AbstractFoo<Nar>{
public Nar(){}
@Override
public Nar instance() {
return new Nar();
}
}
public interface WantToClone< E extends WantToClone<E> >{
public E instance();
}
public class GenericCopyClass< S extends WantToClone<S> >{
public GenericCopyClass(){}
public List<S> copyList(List<S> original){
List<S> temp = new ArrayList<S>();
for(S item : original){
temp.add( item.instance() );
}
return original;
}
}
Upvotes: 1