我有这样的类:
abstract class Person{void toDrink(Liquid l);}
class Liquid{}
class Alcohol extend Liquid{}
class Milk extends Liquid{}
class Adult extends Person{void toDrink(Liquid l){}}
class Child extends Person{void toDrink(Liquid l){}}
我想孩子和成人不把液体作为参数,但牛奶和酒精分别,但我必须覆盖抽象方法与确切的液体参数。所以当我写
Person child = new Child();
child.toDrink(new Alcohol());
孩子可以以酒精为理由喝酒。我可以使用exception或if()来解决这个问题,但是我要求您建议我为这些关系设计一个更好的设计。我想要它,当我传递一个错误的参数给toDrink()方法(酒精到儿童或牛奶到成人)我的IDE强调它作为一个错误和编译错误,当我试图运行它。
您可以创建如下?
abstract class Person<T extends Liquid>{
void toDrink(T l) {
}
}
在上面的代码中,您绑定了toDrink()
方法来接受扩展Liquid
的类型
class Adult<T extends Alcohol> extends Person<T>{
void toDrink(T l){
}
}
class Child<T extends Milk> extends Person<T>{
void toDrink(T l){
}
}
在上面的代码中,您绑定了Adult
和Child
方法的toDrink()
,以接受分别扩展Alcohol
和Milk
的类型。
现在,正如您所期望的那样,下面的代码失败了(带有编译错误)
Person<Milk> child = new Child<Milk>();
child.toDrink(new Alcohol()); // error here
但是这个可以
child.toDrink(new Milk());
你可以使用泛型来解决这个问题:
我建议在Liquid
和Milk
之间创建一个类:
public abstract class NonAlcoholicLiquid extends Liquid {}
public class Milk extends NonAlcoholicLiquid {}
和分别修改你的Person类
public abstract class Person<Drink extends Liquid> {
void doDrink(Drink drink) {
}
}
public class Adult<Drink extends Liquid> extends Person<Drink> {
void doDrink(Drink drink){
}
}
public class Child<Drink extends NonAlcoholicLiquid> extends Person<Drink> {
void doDrink(Drink drink){
}
}
这样儿童只能喝不含酒精的液体,而成人仍然可以喝牛奶;)
更新:根据你的评论,我们可以暂时跳过泛型:
public abstract class Person {
public abstract void doDrink(Liquid drink);
}
public class Adult extends Person {
void doDrink(Liquid drink) {
if(!(drink instanceof Alcohol)) {
throw new InvalidDrinkException("Adults may only drink Alcohol");
}
// do the adult's drinking stuff
}
}
public class Child extends Person {
void doDrink(Liquid drink){
if(!(drink instanceof Milk)) {
throw new InvalidDrinkException("Children may only drink Milk");
}
// do the child's drinking stuff
}
}
但是你的方法在思考上有一个缺陷:当一个孩子长大后,实例是一样的,但是类必须改变…
I want Child and Adult not to take Liquid as args but Milk and Alcohol respectively
表示成人只喝酒精饮料,儿童只喝牛奶。因此,您可以使用泛型,每个Person子类型饮用的液体类型作为类型参数。
abstract class Person<L extends Liquid> {
void toDrink(L l) {
//implementation here.
}
}
class Liquid{}
class Alcohol extend Liquid{}
class Milk extends Liquid{}
class Adult extends Person<Alcohol>{
// You don't necessarily need to override the toDrink method.
}
class Child extends Person<Milk>{ }
您不需要在每个子类中重写toDrink()
方法。在抽象Person类中只能有一个实现。