我有一个关于Java继承和组合的最佳实践的问题:
假设您有一个水果,它可以通过苹果和柠檬来补充。
在这些旁边,您还获得了一个AppleBasket扩展的购物篮
和柠檬篮。
水果与它们之间具有双向的一对多关系
各个篮子,所以水果有一个篮子,篮子有清单
水果
现在我想做的就是强制AppleBasket只能在编译时使用Apple,LemonBaskets也一样。同样,Apple应该仅具有AppleBasket作为属性,Lemons也应具有。
我尝试使用泛型,抽象方法和受保护的变量,但是我总是发现不采用某种方法的原因。重要的是我们不要违反SOLID原则,因此,例如,超类应包含has-a和has-many属性,以避免代码重复等等。
当有人试图将Lemon放入AppleBasket或反之时,这是获得编译器错误的关键。
干杯,
安德烈亚斯
最佳答案
通过对协方差和反方差进行谷歌搜索,您可能会发现一些有关更复杂类型的有用信息。
如果您不介意使用Scala编译为可与Java程序一起使用的字节码,则Scala会为您提供一些不错的语法来完成这种事情(稍后再介绍Java):
水果类
类别购物篮[T def addToBasket(fruit:T)= {}
}
苹果延伸水果
柠檬延伸水果
class AppleBasket扩展购物篮[Apple]
val applebasket =新的AppleBasket
applebasket.addToBasket(新苹果)
applebasket.addToBasket(新柠檬)
此代码段的最后一行给出了编译时错误:
$ scala Test.scala
C:\ cygwin \ home \ user \ Test.scala:18:错误:类型不匹配;
找到:this。柠檬
必需:this.Apple
applebasket.addToBasket(新柠檬)
^
发现一个错误
最近,我一直在与Scala一起玩,在Java中很难考虑到这一点,但是在Java中,我可能会做更多这样的事情:
水果类{}
苹果扩展水果类{}
柠檬延伸水果{}
class Basket {
公共无效addToBasket(T foo){}
}
布拉类{
无效doIt(){
苹果a =新的Apple();
购物篮b =新的购物篮();
b.addToBasket(a);
柠檬l =新柠檬();
b.addToBasket(l);
}
}
b.addToBasket(l)行给出以下编译时类型错误:
Basket 类型的方法addToBasket(Apple)不适用于参数(Lemon)
产生相同编译错误的另一个选项(从注释复制以使其更清楚):
//水果,苹果和购物篮的定义相同,但具有:
class AppleBasket扩展了Basket {}
布拉类{
无效doIt(){
苹果a =新的Apple();
Basket b =新的AppleBasket();
b.addToBasket(a);
柠檬l =新柠檬();
b.addToBasket(l);
}
}