如何通过抽象基类统一处理具有相同属性的不同类

本文介绍如何利用面向对象的继承机制,通过定义抽象基类提取共用字段与方法,使同一函数能安全、简洁地操作多个结构相似但不完全相同的类,避免代码重复。

本文介绍如何利用面向对象的继承机制,通过定义抽象基类提取共用字段与方法,使同一函数能安全、简洁地操作多个结构相似但不完全相同的类,避免代码重复。

在实际开发中,我们常遇到多个类拥有部分相同字段(如 numerator 和 denominator)和对应 getter 方法,但又各自承载不同业务语义(如 A 表示用户分数、B 表示配置项)。若为每个类单独编写逻辑相同的计算函数(如 F()),不仅违反 DRY(Don’t Repeat Yourself)原则,还会增加维护成本与出错风险。

最直接且类型安全的解决方案是提取公共契约,使用抽象基类统一建模。具体做法如下:

  1. 定义抽象基类:封装共用字段及标准访问接口,声明为 abstract 以防止直接实例化;
  2. 让具体类继承该基类:A 和 B 分别扩展基类,并保留各自特有的字段(如 firstName、address);
  3. 函数参数类型上移:将函数 F 的形参类型从具体类改为基类,实现多态调用。

以下是完整可运行的 Java 示例代码:

public abstract class AbstractFraction {
    protected Long numerator;
    protected Long denominator;

    // 构造器(可选)
    public AbstractFraction(Long numerator, Long denominator) {
        this.numerator = numerator;
        this.denominator = denominator;
    }

    // Getter 方法(必须提供,供 F() 调用)
    public Long getNumerator() { return numerator; }
    public Long getDenominator() { return denominator; }

    // Setter 方法(按需添加)
    public void setNumerator(Long numerator) { this.numerator = numerator; }
    public void setDenominator(Long denominator) { this.denominator = denominator; }
}

class A extends AbstractFraction {
    private String firstName;

    public A(Long numerator, Long denominator, String firstName) {
        super(numerator, denominator);
        this.firstName = firstName;
    }

    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
}

class B extends AbstractFraction {
    private String address;

    public B(Long numerator, Long denominator, String address) {
        super(numerator, denominator);
        this.address = address;
    }

    public String getAddress() { return address; }
    public void setAddress(String address) { this.address = address; }
}

public class FractionUtil {
    /**
     * 统一处理任意继承自 AbstractFraction 的子类实例
     * @param input 非 null,且 denominator 不应为 0(调用方需保证)
     * @return 计算结果,注意 Long 除法会截断,建议转为 double 运算
     */
    public static Double F(AbstractFraction input) {
        if (input == null || input.getDenominator() == null || input.getDenominator() == 0L) {
            throw new IllegalArgumentException("Denominator cannot be null or zero");
        }
        // 显式转换为 double,避免整数除法丢失精度
        return input.getNumerator().doubleValue() / input.getDenominator().doubleValue();
    }
}

调用示例

A a = new A(3L, 4L, "Alice");
B b = new B(5L, 2L, "123 Main St");

System.out.println(FractionUtil.F(a)); // 输出: 0.75
System.out.println(FractionUtil.F(b)); // 输出: 2.5

⚠️ 注意事项

该方案兼顾类型安全、可读性与可扩展性——未来新增类 C 只需继承 AbstractFraction,即可无缝接入现有函数体系。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。