You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中子类DiscountProduct的相等性测试实现咨询

Fixing Equality Testing for DiscountProduct (and Fixing Existing Bugs)

Hey there! Let's sort out this equality testing issue step by step. First, your existing code has some critical bugs that are breaking equality checks entirely—let's fix those first, then implement the correct equals method for DiscountProduct.

First: Fix the Broken Equality Logic in Product and Order

1. Product Class's equals Method (Major Bug!)

Right now, your Product.equals incorrectly casts the input obj to Order—that's a huge mistake! The equals method for Product should compare other Product instances, not Orders. Here's the corrected version:

import java.util.Objects;

public class Product implements Comparable<Product> {
    private String productCode;
    private String description;
    private int unitPrice; //pence

    public Product(String productCode, String description, int unitPrice) {
        this.productCode = productCode;
        this.description = description;
        this.unitPrice = unitPrice;
    }

    // Corrected equals method for Product
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false; // Strict type check to preserve symmetry
        Product other = (Product) obj;
        return unitPrice == other.unitPrice
                && productCode.equals(other.productCode)
                && description.equals(other.description);
    }

    // Required by Java's Object contract when overriding equals
    @Override
    public int hashCode() {
        return Objects.hash(productCode, description, unitPrice);
    }

    // Implement Comparable as needed (omitted for brevity)
    @Override
    public int compareTo(Product o) {
        return this.productCode.compareTo(o.productCode);
    }
}

2. Order Class's equals Method (Bug Fix)

Your Order.equals has a mistake: product.equals(obj) is passing the entire Order object to Product's equals, which is wrong. You need to compare the product field of the other Order. Also, always override hashCode when you override equals!

import java.util.Objects;

public class Order implements Comparable<Order> {
    private int quantity;
    private Product product;

    public Order(int quantity, Product product) {
        this.quantity = quantity;
        this.product = product;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Order other = (Order) obj;
        return quantity == other.quantity
                && Objects.equals(product, other.product); // Compare the two Product instances correctly
    }

    @Override
    public int hashCode() {
        return Objects.hash(quantity, product);
    }

    public Product getProduct() {
        return product;
    }

    // Implement Comparable as needed (omitted for brevity)
    @Override
    public int compareTo(Order o) {
        return this.product.compareTo(o.product);
    }
}

Now: Implement DiscountProduct's equals Method

For DiscountProduct, we need to extend the equality check to include the discountRate field, while still honoring the parent class's equality logic. Here's how to do it correctly:

import java.util.Objects;

public class DiscountProduct extends Product {
    private double discountRate;

    public DiscountProduct(String productCode, String description, int unitPrice, double discountRate) {
        super(productCode, description, unitPrice);
        this.discountRate = discountRate;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        // First verify parent class fields are equal
        if (!super.equals(obj)) return false;
        // Now compare DiscountProduct-specific field
        DiscountProduct other = (DiscountProduct) obj;
        // Use Double.compare to avoid floating-point precision issues
        return Double.compare(other.discountRate, discountRate) == 0;
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), discountRate);
    }

    // Optional getter for discountRate (useful for other logic)
    public double getDiscountRate() {
        return discountRate;
    }
}

Key Notes:

  • Strict Type Check: Using getClass() != obj.getClass() instead of instanceof ensures symmetry—if a.equals(b) is true, b.equals(a) must also be true. Using instanceof would break this contract (a Product might match a DiscountProduct, but the reverse wouldn't hold).
  • Floating-Point Equality: Never use == directly for double values—Double.compare() handles precision edge cases properly.
  • HashCode Contract: Overriding hashCode alongside equals is mandatory—this ensures consistent behavior in collections like HashMap or HashSet.

How This Works for Your Use Case

When comparing two Order instances with DiscountProducts:

  1. The Order's equals checks the quantity, then calls product.equals(otherProduct).
  2. Since the product is a DiscountProduct, it first validates all parent Product fields via super.equals(), then compares the discountRate.

This ensures full equality checking across the entire class hierarchy.

内容的提问来源于stack exchange,提问作者Muhammad Mansha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:07:41