使用java泛型来确保收到的参数与其类或子类型相同 [英] Using java generics to ensure that argument received is same as class or subtype thereof

查看:120
本文介绍了使用java泛型来确保收到的参数与其类或子类型相同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 接口动物{
void partner(Animal other);我有一个新手问题。
}

类Lion实现Animal {
int areaUnderControl;
@Override
公共无效合作伙伴(动物其他){
狮子狮子=(狮子)其他;
this.areaUnderControl + = lion.areaUnderControl;
}
}

类人类实现动物{
int money;
@Override
public void partner(Animal other){
Human human =(Human)other;
this.money + = human.money;


$ / code $ / pre

我希望只有具体实现中的伙伴方法接收其类型或其子类型的参数。一种解决方案是使用泛型将Animal定义为:

  interface Animal< T extends Animal< T>> {
void partner(T other);
}

类Lion实现Animal< Lion> {
int areaUnderControl;
@Override
public void partner(Lion other){
this.areaUnderControl + = other.areaUnderControl;
}
}

类人类实现Animal< Human> {
int money;
@Override
public void partner(Human other){
this.money + = other.money;


然而有人仍然会滥用这个功能

 类Bear实现Animal< Lion> {
int honey;
@Override
public void partner(Lion other){
this.honey + = other.areaUnderControl; //问题
}
}

熊有意与狮子。有没有办法,我可以把它绑定到 的类型和子类型。



我尝试搜索现有的问题,并以某种方式感觉设计的界面本身可能有缺陷。如果有人能指出为什么这是错误的或正确的方式来实现这一点,将不胜感激。



谢谢!

解决方案

无法在界面级强制执行此操作,因为从类型安全性的观点没有理由这样做。那么,如果可以定义一个类,Bear实现Animal< Lion> 呢?它本身就是类型安全的(即不会抛出意想不到的ClassCastException,等等) - 这就是泛型所要做的。

事实上,从类型安全(很可能你只需要 interface Animal< T> (类似于接口Comparable< T> )。是的,这将允许某人定义实现Animal的奇怪类,其类型参数是完全不相关的类。所以呢? 本身没有任何问题。



使用这个界面的地方,他们可以强制执行你想要的关系,如 public< T extends Animal <? super T>> void someMethodThatUsesAnimal(T animal)。因为它只存在于使用的地方,所以它确实关心合作伙伴方法是否将其本身作为参数。这类似于如何使用 Comparable (例如 public< T extends Comparable<?super T>> void sort(List< T> list )


I have a newbie question.

interface Animal {
    void partner(Animal other);
}

class Lion implements Animal {
    int areaUnderControl;
    @Override
    public void partner(Animal other) {
        Lion lion = (Lion) other;
        this.areaUnderControl += lion.areaUnderControl; 
    }
}

class Human implements Animal {
    int money;
    @Override
    public void partner(Animal other) {
        Human human = (Human) other;
        this.money += human.money;
    }
}

I want that the partner method in the concrete implementations only receive parameters of its type or its subtype. One solution is to use generics to define Animal as:

interface Animal<T extends Animal<T>> {
    void partner(T other);
}

class Lion implements Animal<Lion> {
    int areaUnderControl;
    @Override
    public void partner(Lion other) {
        this.areaUnderControl += other.areaUnderControl; 
    }
}

class Human implements Animal<Human> {
    int money;
    @Override
    public void partner(Human other) {
        this.money += other.money;
    }
}

However someone can still abuse this as

class Bear implements Animal<Lion> {
    int honey;
    @Override
    public void partner(Lion other) {
        this.honey += other.areaUnderControl; //Problem
    }
}

where a Bear is aspiring to partner with Lion. Is there someway that I can tie it to the type and subtypes of this

I tried searching through the existing questions and somehow I feel the design of the interface itself may be flawed. If someone can point out why this is wrong or the right way to achieve this, it would be greatly appreciated.

Thanks!

解决方案

There is no way to enforce this at the interface level, because there is no reason to do so from a type safety point of view. So what if it's possible to define a class Bear implements Animal<Lion>? By itself, it's type safe (i.e. will not throw unexpected ClassCastException, etc.) -- that's the whole point that Generics is for.

In fact, from a type safety point of view, most likely you just need interface Animal<T> (analogous with interface Comparable<T>). Yes, this will allow someone to define strange classes that implement Animal with a type parameter that is a completely unrelated class. So what? There is nothing wrong with that per se.

In the places that use this interface, they can enforce the relationship that you want, like public <T extends Animal<? super T>> void someMethodThatUsesAnimal(T animal). Because it is only in the places that use it that really cares whether the partner method takes itself as a parameter. This is analogous to how Comparable is used (e.g. public <T extends Comparable<? super T>> void sort(List<T> list))

这篇关于使用java泛型来确保收到的参数与其类或子类型相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆