如何通过通用模板“安全地”使用多态?

德克萨斯州

我有一些类可以实现的接口:

interface Vehicle {}

class Car implements Vehicle {}

class Bicycle implements Vehicle {}

我还有另一个具有此方法的getter和setter的接口:

interface Person {
    public ArrayList<Vehicle> getVehicles();
    public void setVehicles (ArrayList<Vehicle> vs);
}

一些类实现了它:

class CarOwner implements Person {
    public ArrayList<Car> cars;
    public ArrayList<Car> getVehicles() {
        return cars;
    }
    public void setVehicles(ArrayList<Car> cars) {
        this.cars = cars;
    }
}

class BicycleOwner implements Person {
//...
}

但是,它抱怨设置器与接口具有相同的擦除,但没有覆盖它。我必须将to更改ArrayList<Vehicle>ArrayList,并将其强制转换为函数,但是它不是“安全的”(我知道它应该可以工作,但其他人可能不能)。如何处理这种情况?


编辑:

当我将代码更改为答案时,它不再抱怨。但是当我使用它时,例如

//I have an arraylist of Person
ArrayList<Person> persons;
//...
Vehicle first = persons.get(0).getVehicles().get(0);

它抱怨类型的第一行需要一个参数...但是它可以是任何类型的person,因为Arraylist persons可以包含所有类型的Person。如何执行此操作?还是必须保留它而没有模板参数?


编辑2:

我在那里更新了答案,发现当我打电话给setter时再次引发错误...

Person<?> personA = persons.get(0);
ArrayList<Vehicle> vs = new ArrayList<Vehicle>();
//vs.add(carA);    
personA.setVehicles(vs);  

最后一行给出错误:This gives error saying The method setVehicles(ArrayList<capture#6-of ?>) in the type Post<capture#6-of ?> is not applicable for the arguments (ArrayList<Vehicle>)我尝试更改为,ArrayList<?>但不起作用...

天蓝色的青蛙

您的问题是您的接口被声明为接受an ArrayList<Vehicle>,但是您正在尝试使用采用的方法来实现它ArrayList<Car>有人可以调用您的接口,并合法地将其交给其他类型的扩展工具列表,因此您的代码将无法编译。

您想要做的是使您的Person接口通用,以便它可以采用任何可扩展的类型Vehicle,然后使之CarOwner成为实现的类Person<Car>

interface Person<T extends Vehicle> {
    public ArrayList<T> getVehicles();
    public void setVehicles (ArrayList<T> vs);
}

class CarOwner implements Person<Car> {
    public ArrayList<Car> cars;
    public ArrayList<Car> getVehicles() {
        return cars;
    }
    public void setVehicles(ArrayList<Car> cars) {
        this.cars = cars;
    }
}

编辑以回答问题的编辑

好吧,如果您要使用raw ArrayList<Person>,那么实际上只是将类型错误从类定义转移到了对它的使用。参数化后Person,还需要以这种方式使用它:

    ArrayList<Person<?>> persons = new ArrayList<>();
    // ...
    Vehicle first = persons.get(0).getVehicles().get(0);

您可以在此处了解有关Java通配符的更多信息

编辑2

是的,通配符的缺点是编译器不知道类型。在这种情况下,您可以只使用Vehicle接口,因为您确实知道所有内容都在扩展:

    ArrayList<Person<Vehicle>> persons = new ArrayList<Person<Vehicle>>();
    // ...
    Person<Vehicle> personA = persons.get(0);
    ArrayList<Vehicle> vs = new ArrayList<Vehicle>();
    //vs.add(carA);    
    personA.setVehicles(vs);

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何通过通用模板“安全地”使用多态?

来自分类Dev

通过SSH安全地使用VNC

来自分类Dev

如何安全地存储api密钥,模板文件

来自分类Dev

如何使用不同的线程通过openmp安全地更新C结构

来自分类Dev

如何通过DBUS接收的数据安全地使用g_variant_iter_loop

来自分类Dev

如何使用Java / HTML表单通过网页安全地创建neo4j节点

来自分类Dev

如何安全地通过ssh返回bash数组?

来自分类Dev

在Angular中通过$ scope安全地使用eval()

来自分类Dev

安全地使用WeakReference

来自分类Dev

如何使用GCD安全地锁定变量?

来自分类Dev

如何使用PouchDB安全地连接到Cloudant?

来自分类Dev

如何安全地在主线程上使用[NSTask waitUntilExit]?

来自分类Dev

如何使用Net :: OpenSSH安全地写入远程文件

来自分类Dev

如何使用open()安全地设置标志?

来自分类Dev

如何安全地使用coxph和子集或权重?

来自分类Dev

如何使用TeamCity安全地进行生产发行?

来自分类Dev

如何安全地使用C中的枚举?

来自分类Dev

如何使用GCD安全地锁定变量?

来自分类Dev

如何安全地使用JSON.stringify?

来自分类Dev

如何使用Net :: OpenSSH安全地写入远程文件

来自分类Dev

如何使用存储的函数安全地检索sql数据

来自分类Dev

如何使用套接字安全地实现通知系统?

来自分类Dev

如何在 CircleCI 中安全地使用 Gemfury 令牌?

来自分类Dev

如何安全地扩展Ubuntu分区?

来自分类Dev

如何安全地销毁QThread?

来自分类Dev

如何安全地发布StringBuffer?

来自分类Dev

如何快速安全地存储密码?

来自分类Dev

如何安全地搬运包裹intellij?

来自分类Dev

如何安全地重构动态语言?

Related 相关文章

热门标签

归档