我有一个关于 Java 继承和组合最佳实践的问题:
Say you've got a Fruit which gets extended by Apple and Lemon.
Next to these you also got a Basket that gets extended by AppleBasket and LemonBasket.
Fruits have a bidirectional one-to-many relationship with their respective baskets, so Fruits have a basket, and baskets have a list of fruits.
现在我想做的就是强制 AppleBasket 在编译时只包含 Apple,LemonBaskets 也是如此。类似地,Apple 应该只具有 AppleBasket 作为属性,Lemons 也是如此。
我尝试过使用泛型、抽象方法和 protected 变量,但我总是找到不采用某种方法的理由。重要的是我们不要违反 SOLID 原则,因此例如父类(super class)应该包含 has-a 和 has-many 属性以避免代码重复等。
当有人试图将 Lemon 放入 AppleBasket 时,出现编译器错误的关键是,反之亦然。
干杯, 安德烈亚斯
最佳答案
通过谷歌搜索协变和逆变,您可能会找到一些有关更复杂类型的有用信息。
如果您不介意使用 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); } }
关于java - 在 Java 编译时检查组合与继承约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11842001/