【问题标题】:Java Generic Class which Implements a Generic Interface实现泛型接口的 Java 泛型类
【发布时间】:2018-02-08 22:31:03
【问题描述】:

最初我想创建一种实现“X”接口的深度复制对象的通用方法。但是,我不想为每个实现“X”的类编写一个复制列表函数。相反,我创建了一个通用类,它与接口“X”绑定它是通用的。

问题在于,如果类“A”实现了“X”并包含(做)/(不)实现“X”的子类。您如何阻止子类从“X”的“A”实现继承并强制它们自己的实现,而不必为每个子类实现“X”。

我很确定这在 java 中是不可能的,因为继承和泛型。

这是迄今为止的实现,但我需要一个类型转换,它为不继承接口“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;
    }

}

输出如下:

Hello, World
Foo
Foo
Foo
Bar
Bar
Bar
Foo
Foo
Foo

*编辑 1

问题:

隐式类型转换:

temp.add((S)item.instance());

接口没有明确指定类实例:

interface WantToClone&lt;E extends WantToClone&lt;E&gt;&gt;

【问题讨论】:

  • “子类不继承接口 X”。但是它们都继承了 X。你能在代码中准确地显示你想要解决的问题吗?
  • ' temp.add((S)item.instance()); ' 在 GenericCopyClass 中
  • 子类extend超类,从而继承超类的所有接口和非私有方法。所以我不确定你所说的“不继承接口'X'的子类的不安全操作”是什么意思,因为所有子类都继承接口X,包括Foo中的实现。
  • 不安全的操作是Nar类不包含instance方法,因此GenericCopyClass必须调用Foo的继承接口方法,导致@的类型转换副本987654331@。这是危险的,因为 Foo 不包含 Nar 的任何特化,但我们有一个 Nar 类型的 Foo 对象列表。

标签: java generics inheritance


【解决方案1】:

我会使用包含所有常用方法的参数化抽象类,并让子类只实现instance 方法:

    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;
        }    
    }

【讨论】:

  • 这是一个很好的解决方案,因为它强制用户实现接口,并限制创建任何类型不正确的类。但是,通过这样做,没有其他类可以继承实例“Nar”或“Bar”......我会对在编译时对正在访问子类方法签名“实例”的类抛出错误的解决方案感兴趣子类不包含,但父类包含。但是,我认为这违反了继承的原则。谢谢你的回答。
  • 您面临的问题是继承不能按您期望的方式工作。没有什么可以阻止您在 Nar 类上调用 instance。在超类/接口上定义方法后,所有子类都将具有该方法。
猜你喜欢
  • 2015-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多