【问题标题】:Trouble running methods on objects of a polymorphic array in Java在 Java 中对多态数组的对象运行方法时遇到问题
【发布时间】:2015-09-13 04:23:30
【问题描述】:

我被分配了 2 个课程:Sale 和 DiscountSale(扩展了 Sale)。我应该创建一个名为 MultiItemSale 的新类,它将创建一个包含 Sale 和 DiscountSale 对象的数组(购物车)。但我无法从 DiscountSale 获取方法来处理数组中的 DiscountSale 对象。

类 Sale(基类)有一些方法,特别是 setName() 和 setPrice()。

DiscountSale 类扩展了 Sale,因此它可以使用 setName() 和 setPrice(),但它也有 setDiscount() 等等。

在 MultiItemSale 中:

Sale[] shoppingCart = new Sale[numOfItems];

据我了解,由于 DiscountSale 扩展了 Sale,Sale 和 Discount Sale 对象都应该能够放置在这个数组中,对吗?

我使用 for 循环来询问商品是否打折。如果不是,那么:

shoppingCart[i] = new Sale();

如果打折:

shoppingCart[i] = new DiscountSale();

这就是我开始遇到问题的地方:

以下工作,因为 setName() 和 setPrice() 来自 Sale 类

此外,这一切都在一个 if 语句下,如果商品打折,那么:

shoppingCart[i] = new DiscountSale();
shoppingCart[i].setName(name);
shoppingCart[i].setPrice(price);

但如果我尝试这样做,我会收到错误,因为 setDiscount() 来自 DiscountSale:

shoppingCart[i].setDiscount(discount);

Eclipse 告诉我,“方法 setDiscount(double) 未定义 Sale 类型”。如果

shoppingCart[i] = new DiscountSale();

为什么我不能在该对象上使用 DiscountSale 中的方法?我想我对多态性和数组的工作方式有误解。

【问题讨论】:

标签: java arrays


【解决方案1】:

所有编译器都知道你有Sales,所以这些是你可以使用的唯一方法。多态性适用于当您对不同类型的对象进行相同函数调用的情况,并且相同的函数调用将根据它是什么类型的对象而表现不同。

在此示例中,名称、价格和折扣可以是您的构造函数的参数。这样你就可以在你说new的时候传递它们,之后你就不必调用设置方法了。

编辑:看着the Wikipedia article on the Circle-Ellipse Problem,我想到任何Sale 都隐含0% 的折扣。您只能使用DiscountSales 并能够访问他们的所有成员,可能包括一个指示是否可以更改折扣的标志。

【讨论】:

  • 感谢您的回答。我也想过这样做,这是一个很好的解决方案,但唯一的问题是,在项目的后期,我必须这样做,以便用户可以返回并编辑购物车中各个项目的一些详细信息。所以假设用户将折扣设为 20%,我需要让他们说它实际上只有 15%,并且能够运行 shoppingCart[i].setDiscount(newDiscount) 真是太棒了。如果他们想编辑特定项目的详细信息,我想我可以创建一个新对象。
【解决方案2】:

用面向对象设计的说法,DiscountSaleSale.

通常,程序会将SaleDiscoutSale 对象收集到同一个Sale 集合中,以便对Sale API 定义的集合中的这些对象执行常见的Sale 处理。因此,尝试使用如下语句没有多大意义:

Sale[] shoppingCart = new Sale[] { ... };
    :
    :
shoppingCart[i].setDiscount(...);

因为Sale 不是DiscountSale,所以在顶级Sale 项目上设置折扣率,正如您所设计的那样,不是其API 的一部分,并且声明不会很有道理。

DiscountSale 对象将继承 Sale 的方法(DiscountSale Sale),但Sale 对象将不知道定义的任何子类特定方法在DiscountSale 中(Sale 对象不必是DiscountSale)。

那该怎么办?

此类问题的常见解决方案是利用多态性。例如,在您的 Sale 类中,将 getNetPrice() 等方法作为其 API 的一部分。

public class Sale {

    protected double price;
    :
    :
    public double getPrice() { return price; } // return original price

    public double getNetPrice() { return price; } // return discounted price
    :
    :
}

注意Sale 中的两个方法是相同的。怎么会?因为他们的合约是不同的。第一个返回原始价格。第二个指定返回折扣价。因为Sale 对象没有折扣,所以它也简单地返回原价。

但是,DiscountSale 类将利用多态性来履行 API 契约:

public class DiscountSale extends Sale {

    private double discountRate; // specified as percent off (0.0 to 1.0)
    :
    :

    @Override
    public double getNetPrice() { 
        return (super.price - (super.price * discountRate)); 
    }
    :
    :
}

这里定义了DiscountSale 对象,以便在创建对象时设置折扣率。这非常简单,因为正如我们所说,为集合中的Sale 对象设置折扣率(可能会或可能不会打折)更令人困惑。

DiscountSale 使用Sale 合约并覆盖getNetPrice() 方法来计算并返回折扣价。通过这种方式,两个对象可以在同一个集合中并共享一个公共 API 以获得非折扣或折扣价格。

【讨论】:

  • 谢谢。我想在不更改 Sale 和 DiscountSale 类中的任何内容的情况下创建 MultiItemSale 类,但问题从未说过我无法编辑两个给定的类,所以这可能是个好主意。
猜你喜欢
  • 2020-08-06
  • 2015-07-26
  • 2020-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多