Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 方法中的多个泛型_Java_Generics_Inheritance_Multiple Inheritance_Type Parameter - Fatal编程技术网

Java 方法中的多个泛型

Java 方法中的多个泛型,java,generics,inheritance,multiple-inheritance,type-parameter,Java,Generics,Inheritance,Multiple Inheritance,Type Parameter,我的主要问题是,如果一个泛型对象扩展了例如4种类型,我是否可以将它绑定为两种类型。如果没有一个例子,我真的不知道如何问这个问题 所以我创建了一个简单游戏的小例子,在这个游戏中,战士或游侠可以装备不同类型的武器(单手、双手、近战、远程)。每种武器都有两个属性。因此,例如武器类型匕首扩展了单手近战武器装备 游侠职业(可以使用双手远程武器): 这里的主要问题是(我认为)我不知道如何实现一个战士可以装备不同属性的不同武器(例如弓(远程,双手)或匕首(近战,单手)),而游侠只有一种可能性。如何解决此问题?

我的主要问题是,如果一个泛型对象扩展了例如4种类型,我是否可以将它绑定为两种类型。如果没有一个例子,我真的不知道如何问这个问题

所以我创建了一个简单游戏的小例子,在这个游戏中,战士或游侠可以装备不同类型的武器(单手、双手、近战、远程)。每种武器都有两个属性。因此,例如武器类型
匕首扩展了单手近战武器装备

游侠职业(可以使用双手远程武器):


这里的主要问题是(我认为)我不知道如何实现一个战士可以装备不同属性的不同武器(例如弓(远程,双手)或匕首(近战,单手)),而游侠只有一种可能性。如何解决此问题?

由于
Dagger
未实现
Ranged
,因此代码无法编译

我想你指的是近战
或远程。这可以写成重载

<T extends Melee & OneHanded> void equip(T weapon) {
<T extends Ranged & OneHanded> void equip(T weapon) {
void装备(T武器){
空装备(T武器){
请注意,为了使重载具有不同的擦除,顺序发生了变化。但是,最好使用不同的名称,而不是重载


(另外,我会使用一层间接寻址,而不是丢失基本类型的类型信息。)

另一个答案直接解决了问题中的问题。如您所见,使用此设计,您的最佳选择是使用一组
equipXXX()
方法

另一种选择是使用

创建抽象的
武器
武器装饰器
,为以后添加新武器类型提供最大的灵活性

public abstract class Weapon {
...
}

public abstract class WeaponDecorator extends Weapon {
    Weapon _weapon;
    WeaponDecorator(Weapon weapon) {this._weapon = weapon;}
}
将各种武器类型转换为武器装饰器:

public class OneHanded extends WeaponDecorator {
    OneHanded(Weapon weapon) {
        super(weapon);
    }
}

public class Melee extends WeaponDecorator {
    Melee(Weapon weapon) {
        super(weapon);
    }
}
并从
Warrior
类中删除所有泛型:

public class Warrior  {
    private Weapon weapon;
    public void equip(Weapon weapon) {
        this.weapon = weapon;
    }
}
现在,您只需执行以下操作:

Weapon w = new OneHanded(new Melee(new Dagger()));
Warrior warrior = new Warrior();
warrior.equip(w);
下面是一个包含代码和更多说明的示例

编辑

如果您选择此解决方案,还应在运行时解决为选定英雄检查选定武器有效性的责任。例如,这可以添加到
Ranger
装备
方法中:

if(weapon.isMelee()) //error (unacceptable)
但随着规则集变得越来越复杂,您可能希望使用其他模式,例如。不过,所有这些都将委托给运行时。这是您为获得更大的灵活性而付出的代价。当然,您也可以尝试通过创建装饰器的层次结构来获得编译时安全性(类似于java.io library所做的)。但是,这可能会使应用程序过于复杂,速度非常快


最后,如果只有少数这种组合类型(
双手+近战
单手+远程
,等等)选择另一个答案是有意义的,只需再增加一些
装备
方法,并具有编译时类型检查的安全性。

只需创建两个方法,一个用于
T扩展单手和近战
,另一个用于
T扩展单手和远程
。或者完全忽略第二个约束,如
Mellee | Ranged
总是正确的。@HimBromBeere您的第一个解决方案实际上不起作用。编译器会抱怨方法冲突,因为它们具有相同的擦除功能。@jrook正是我想写的。我不能用相同的签名重载方法。不同的泛型不起作用。这可能只是一个示例,但使用编译时约束,他re是过度限制。例如,你不能实现一些功能,比如喝一种药剂,让你只需一只手就能在几天内产生一把双手剑。规格模式非常适合这个问题。是的,这就是我所想的。但是有可能对所有4种不同的武器类型都这样做吗?如果我试图过载所有4种方法,我都不能这样做,因为它们有相同的擦除:
和`为不同的方法使用不同的名称。但是如果你坚持:
你能在这里通过使用一层间接寻址来扩展你的意思吗,也许可以举个例子吗?就是这样它根本没有涉及如何实现组合约束,这是使用类型的最初目标。@plalx我编辑了我的答案,以解决您提出的问题。
public class OneHanded extends WeaponDecorator {
    OneHanded(Weapon weapon) {
        super(weapon);
    }
}

public class Melee extends WeaponDecorator {
    Melee(Weapon weapon) {
        super(weapon);
    }
}
public class Warrior  {
    private Weapon weapon;
    public void equip(Weapon weapon) {
        this.weapon = weapon;
    }
}
Weapon w = new OneHanded(new Melee(new Dagger()));
Warrior warrior = new Warrior();
warrior.equip(w);
if(weapon.isMelee()) //error (unacceptable)