里氏替换原则在抽象类类型特化实现中的合规方案问询
符合里氏替换原则的烘焙食物建模方案
你的核心问题在于抽象类Baked的契约与子类约束冲突:Baked定义了可持有任意Topping的属性,但子类Pizza和Pie却限制只能使用特定子类型的配料,这确实违反了LSP——用Pizza替换Baked实例时,无法满足父类“设置任意Topping”的契约。
要解决这个问题,通过泛型约束抽象类与配料的绑定关系是兼顾契约统一性和LSP的最优方案,具体实现如下:
定义泛型抽象类
Baked<T>,限定T为Topping的子类public abstract class Baked<T extends Topping> { protected T topping; public abstract void setTopping(T topping); public abstract T getTopping(); }让具体子类指定对应的配料类型,严格遵守泛型契约
public class Pizza extends Baked<PizzaTopping> { @Override public void setTopping(PizzaTopping topping) { this.topping = topping; } @Override public PizzaTopping getTopping() { return this.topping; } } public class Pie extends Baked<PieTopping> { @Override public void setTopping(PieTopping topping) { this.topping = topping; } @Override public PieTopping getTopping() { return this.topping; } }配料类保持原有分层结构即可
public abstract class Topping {} public class PizzaTopping extends Topping {} public class PieTopping extends Topping {}
这种方案下,Baked<T>的契约明确为“持有类型为T的配料”,子类Pizza和Pie分别实现对应T的具体约束,用子类替换对应泛型父类实例(比如Baked<PizzaTopping>实例替换为Pizza)完全符合LSP,不会出现“无法设置父类允许的配料”的冲突。
另外,也可以选择不在抽象类中定义通用配料属性,让每个子类自行实现配料管理,但这种方式会丢失抽象类的统一契约,泛型方案是更合理的选择。
内容的提问来源于stack exchange,提问作者magva
相关产品推荐
相关产品推荐

