简体   繁体   English

将子类的ArrayList传递给一个采用超类ArrayList的构造函数?

[英]Passing an ArrayList of subclass to a constructor that takes ArrayList of superclass?

Okay so I'm working on this project for the university and I think I'm doing something wrong here, guess I haven't understood java subclassing and class inheritance enough. 好的,所以我正在为这所大学开展这个项目,我想我在这里做错了,我猜我还没有理解java继承和类继承。

I have rewrote my problem in this little form. 我用这个小形式改写了我的问题。

    class SuperClass {

        int dunno;

        public SuperClass(int dunno) {
            this.dunno = dunno;
        }
    }

    class SubClass extends SuperClass {

        int duncare;

        public SubClass(int dunno, int duncare) {
            super(dunno);
            this.duncare = duncare;
        }
    }

    class VeryBigClass {

        ArrayList<SuperClass> superList;

        public VeryBigClass(ArrayList<SuperClass> superList) {
            this.superList = superList;
        }
    }

    public void main(String[] args) {

        new VeryBigClass(new ArrayList<SubClass>()); // this is the problematic line

    }

}

In little words I wrote a lot of classes that extend one more general class, and in many places I have made operations with the superclass (the general one), instead of treating each of the subclasses one by one in the same way. 简而言之,我编写了许多扩展一个通用类的类,并且在许多地方我使用超类(一般类)进行操作,而不是以相同的方式逐个处理每个子类。

But I can not create the instance of the class I need, since the constructor takes as argument the superclass. 但是我无法创建我需要的类的实例,因为构造函数将超类作为参数。 I don't even know how to cast it since new VeryBigClass(new (ArrayList<SuperClass>)ArrayList<SubClass>()); 因为new VeryBigClass(new (ArrayList<SuperClass>)ArrayList<SubClass>());我甚至不知道如何转换它new VeryBigClass(new (ArrayList<SuperClass>)ArrayList<SubClass>()); is obviously wrong. 显然是错的。 Plus, the construction of these instances will be handled by a json library at some point so I'd rather not do such fancy stuff... 另外,这些实例的构建将在某个时候由json库处理,所以我宁愿不做这些花哨的东西......

If you use generics, it should work just fine, is not the same a list of Superclass than a list of Subclass, but the generic solve this: 如果你使用泛型,它应该工作得很好,不是一个超类列表而不是一个子类列表,但通用解决了这个:

class VeryBigClass<T extends SuperClass> {

    ArrayList<T> superList;

    public VeryBigClass(ArrayList<T> superList) {
        this.superList = superList;
    }
}

The Java Tutorial explains this in http://docs.oracle.com/javase/tutorial/java/generics/inheritance.html Java Tutorial在http://docs.oracle.com/javase/tutorial/java/generics/inheritance.html中解释了这一点。

Bottom line, if you have types with an inheritance relationship, like Sub extends Super as generics, they do not confer an inheritance relationship in the classes that hold them: Foo<Sub> is not a subtype of Foo<Super> . 换句话说,如果您有具有继承关系的类型,例如Sub extends Super为泛型,则它们不会在包含它们的类中赋予继承关系: Foo<Sub>不是Foo<Super>的子类型。

The reason is that it would violate the promise of what type the generic type contains, breaking the Liskov Substitution principle. 原因是它违反了泛型类型所包含的类型的承诺,违反了Liskov Substitution原则。 If List<Sub> extended List<Super> , it would be legal to do this: 如果List<Sub>扩展List<Super> ,则执行此操作是合法的:

List<Sub> subs = new ArrayList<Sub>();
List<Super> supers = subs;

Super super = new Super();
supers.add(super);

Whoa! 哇! Now subs has an element of type Super , completely illegal! 现在subs有一个Super类型的元素,完全违法!

Because ArrayList<Sub> is not a subtype of List<Super> , when you invoked 因为ArrayList<Sub>不是List<Super>的子类型,所以在您调用时

new VeryBigClass(new ArrayList<SubClass>());

you passed an argument to the constructor that was not legal. 您将参数传递给不合法的构造函数。

You can also use the wildcard ? extends super 你也可以使用通配符? extends super ? extends super That is, any class that extends super. ? extends super即任何扩展超级的类。

Example : 示例

class VeryBigClass {

    ArrayList<? extends SuperClass> superList;

    public VeryBigClass(ArrayList<? extends SuperClass> superList) {
        this.superList = superList;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM