【问题标题】:Interface, Classes and Sub-Classes inheritance接口、类和子类继承
【发布时间】:2019-05-06 20:06:34
【问题描述】:

我有一个父类Fruit 和子类FruitUnitFruitWeightFruitVolume,描述了如何购买不同类型的水果。

我必须创建一个接口来实现方法payFruit(),因为fruit 的所有子类都必须实现这个。

interface IFruitPayment {
    double payFruit();
}

假设计算payFruit() 的方法对于每个子类(数量*价格、单位*价格、重量*价格)都不同,我如何创建任何父 Fruit 对象并访问方法 payFruit()儿童班?

在父类中实现 payFruit() 返回 0 的方法解决了这个问题,因为子类可以覆盖它,但看起来不对。

假设我有一个水果数组列表,我想迭代它们以获取方法 payFruit() 的值。

实现这一目标的最佳和最干净的方法是什么?

简介:

在水果店,所有水果都有名称和底价。这家商店以三种方式销售水果:统一、重量和体积。总价的计算方法是将基本价格乘以单位数量、重量或体积,视情况而定。任何类型的水果(例如香蕉、橙子、苹果)都可以按单位、重量或体积进行销售。它旨在开发具有类层次结构的 Java 项目。 The FruitUnit, FruitWeight and FruitVolume classes inherit from the Fruit class。还应该有一个代表要购买的各种水果的 Basket 类。此类应包括以下方法:

  1. 将购买的指定水果放入购物篮;
  2. 计算所购水果的总价值;
  3. 计算给定类型水果(水果名称)的总花费

为了与其他项目的类兼容,执行支付金额计算的方法将在各个类中使用,名称为 payFruit,返回类型为 double 且无参数。该方法必须在接口中声明。

注意: 我知道这对我来说可能看起来很特殊,对其他人来说不是很有帮助,但我发现这个类层次结构有点令人困惑。

【问题讨论】:

  • 那个类层次结构没有意义。这些子类不代表水果的种类。
  • Fruit 实现IFruitPayment 并创建类abstract。然后您可以在Fruit 对象上使用payFruit() 方法,因为该方法是在那里定义的(实际上是在接口中)。
  • 如前所述,您的子类没有通过 is-a 测试。 FruitUnit is-a Fruit, FruitWeight is-a Fruit?我不这么认为。
  • 你说你必须创建一个接口?这是上课的吗?
  • 除了令人困惑的类层次结构,为什么在这种情况下需要接口?难道你不能把Fruit抽象化,把payFruit()抽象化吗?除非你有其他非水果类需要payFruit(),否则使用接口没有多大意义。

标签: java


【解决方案1】:

好的,所以基本上你希望你的子类实现IFruitPayment 接口。

如果您的每个子类都实现了该接口,您可以将它们用作该接口。

List<IFruitPayment> fruitPayments = new ArrayList<>():
        fruitPayments.add(new FruitUnit());
        fruitPayments.add(new FruitVolume());
        fruitPayments.add(new FruitWeight());
        for(IFruitPayment payment:fruitPayments) {
            System.out.println(payment.payFruit());
        }

【讨论】:

    【解决方案2】:

    您可能正在这里寻找不同的结构。很难想象FruitFruitUnit 子类。这是因为IFruitPayment 不是水果。这是您希望子类实现的单独接口。

    这样说,你可以声明Fruit实现IFruitPayment,使FruitUnitFruitWeightFruitVolume 扩展 IFruitPayment,并有Fruit的子类实现其中之一...

    abstract class Fruit implements IFruitPayment {}
    

    除非您需要检查具体的实现类型,否则您应该可以摆脱这三个接口,因为API由IFruitPayment提供。但除此之外:

    interface FruitUnit extends IFruitPayment{}
    interface FruitWeight extends IFruitPayment{}
    interface FruitVolume extends IFruitPayment{}
    

    实际的子类会实现相应的接口:

    class Banana extends Fruit implements FruitWeight {
        public double payFruit() {...}
    }
    
    class Watermelon extends Fruit implements FruitVolume {
        public double payFruit() {...}
    }
    
    //etc.
    

    现在这里有点冗余,IMO。如果子接口有理由这样做,也许它们应该有自己的更清晰的 API,例如通过声明特定于它们自己类型的方法。这是一个虚构的例子来说明这个想法:

    interface FruitUnit extends IFruitPayment{
        double getQuantityPrice();
        default double payFruit() {return this.getQuantityPrice();}
    }
    

    但除非需要,否则这三个子接口实际上是不必要的。

    【讨论】:

    • 泰!我用介绍更新了这个问题。我不确定这是否是按照我的要求做的正确方法。
    【解决方案3】:

    要计算一个水果的价格,您确实有两个顾虑:

    1. 该水果的每“单位”价格
    2. 对于每种水果,它是多少“单位”

    核心的Fruit(无论是抽象类还是接口)只需要提供一个所有实现都必须实现的double getUnit()。从那里开始,这取决于您想要获得的复杂程度;如果这只是一个简单的练习,我会考虑再添加两种方法——一种返回单价,另一种获取水果的成本(只是将它们相乘)。

    您可能会争辩说,单位价格不是Fruit 关心的问题;在这种情况下,您可能有一个完整的其他服务知道每个 Fruit 的价格,这就是可以进行乘法运算的服务。

    编辑:体积、重量、颜色等对于特定实现计算它们的“单位”值来说都是单独重要的,但这取决于你以及这些是否值得在公共界面上使用的情况

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-25
      • 1970-01-01
      • 2014-12-24
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      相关资源
      最近更新 更多