我有一个关于Java继承和最佳实践的问题。组合物:
说你有一个由Apple和Lemon扩展的水果。
除了这些之外,你还有一个由AppleBasket扩展的篮子 和LemonBasket。
水果与他们的双向一对多关系 各自的篮子,所以水果有一个篮子,篮子有一个清单 水果。
现在我要做的是强制AppleBasket只在编译时使用苹果,同样适用于LemonBaskets。同样,Apple应该只有AppleBasket作为财产,同样对于Lemons。
我尝试过使用泛型,抽象方法和受保护变量,但我总是找不到某种方法的理由。重要的是我们不要破坏SOLID原则,例如,超类应该包含has-a和has-many属性以避免代码重复等等。
当有人试图将Lemon放在AppleBasket中时,这是导致编译错误的关键,反之亦然。
干杯, 安德烈亚斯
答案 0 :(得分:0)
您可以通过Google搜索协方差和逆变来找到有关更复杂输入的有用信息。
如果您不介意使用Scala编译为可以与Java程序一起使用的字节码,Scala会为您提供一些很好的语法(Java稍后):
class Fruit class Basket[T <: Fruit ] { def addToBasket(fruit:T) = {} } class Apple extends Fruit class Lemon extends Fruit class AppleBasket extends Basket[Apple] val applebasket = new AppleBasket applebasket.addToBasket(new Apple) applebasket.addToBasket(new Lemon)
此代码段的最后一行给出了编译时错误:
$ scala Test.scala C:\cygwin\home\user\Test.scala:18: error: type mismatch; found : this.Lemon required: this.Apple applebasket.addToBasket(new Lemon) ^ one error found
我最近一直在和Scala一起玩,我在Java中考虑这个问题很困难,但在Java中我可能会做更多这样的事情:
class Fruit{} class Apple extends Fruit{} class Lemon extends Fruit{} class Basket<T extends Fruit>{ public void addToBasket(T foo) {} } class Blah { void doIt() { Apple a = new Apple(); Basket b = new Basket<Apple>(); b.addToBasket(a); Lemon l = new Lemon(); b.addToBasket(l); } }
b.addToBasket(l)行给出以下编译时类型错误:
The method addToBasket(Apple) in the type Basket<Apple> is not applicable for the arguments (Lemon)
另一个提供相同编译错误的选项(从注释中复制以使其更清晰):
//same definition of Fruit, Apple, and Basket, but with: class AppleBasket extends Basket<Apple> {} class Blah { void doIt() { Apple a = new Apple(); Basket<Apple> b = new AppleBasket(); b.addToBasket(a); Lemon l = new Lemon(); b.addToBasket(l); } }