
本文介绍如何利用面向对象的继承机制,通过定义抽象基类提取共用属性与方法,使同一函数能安全、简洁地处理多个具有部分相同结构的类实例,避免代码重复并提升可维护性。
本文介绍如何利用面向对象的继承机制,通过定义抽象基类提取共用属性与方法,使同一函数能安全、简洁地处理多个具有部分相同结构的类实例,避免代码重复并提升可维护性。
在实际开发中,我们常遇到多个类拥有部分相同字段(如 numerator 和 denominator)和对应 getter 方法,但又各自携带专属业务属性(如 firstName 或 address)。若为每个类单独编写逻辑相同的计算函数(如浮点除法),不仅违反 DRY(Don’t Repeat Yourself)原则,还会增加后续维护成本。
最直接且符合 Java 设计规范的解决方案是:提取公共契约,构建抽象基类。
首先,定义一个抽象类 AbstractFraction,封装所有共用状态与行为:
public abstract class AbstractFraction {
protected Long numerator;
protected Long denominator;
// 提供标准 getter(注意:返回类型为 Long,除法需显式转型)
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;
}
}接着,让具体业务类 A 和 B 继承该基类:
class A extends AbstractFraction {
private String firstName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
class B extends AbstractFraction {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}最后,将原函数 F 封装为工具方法,参数类型声明为 AbstractFraction —— 此时编译器即可保证传入对象必定具备 getNumerator() 和 getDenominator() 方法:
public class FractionUtil {
/**
* 安全执行分数除法:要求输入对象必须提供 numerator/denominator 的 getter
* @param input 非 null 的 AbstractFraction 子类实例
* @return 分子除以分母的 double 结果;若分母为 null 或零,建议额外校验
*/
public static Double F(AbstractFraction input) {
if (input == null) {
throw new IllegalArgumentException("Input cannot be null");
}
Long num = input.getNumerator();
Long den = input.getDenominator();
if (den == null || den == 0L) {
throw new ArithmeticException("Denominator cannot be null or zero");
}
return num.doubleValue() / den.doubleValue();
}
}✅ 使用示例:
A a = new A(); a.setNumerator(3L); a.setDenominator(4L); System.out.println(FractionUtil.F(a)); // 输出: 0.75 B b = new B(); b.setNumerator(5L); b.setDenominator(2L); System.out.println(FractionUtil.F(b)); // 输出: 2.5
⚠️ 注意事项:
- 若 A 和 B 已存在其他父类(Java 不支持多重继承),则应改用 接口 + 默认方法 + 组合 方案(例如定义 Fractionable 接口,并在各子类中委托实现);
- 实际项目中建议配合 Objects.requireNonNull() 或断言增强健壮性;
- 除法结果为 Double,需注意 null 值解包异常(Long.doubleValue() 对 null 会 NPE),因此务必提前判空;
- 若未来需扩展更多“分数类”,只需继承 AbstractFraction 即可无缝接入现有逻辑,体现良好开闭原则(OCP)。
该设计兼顾类型安全、语义清晰与扩展弹性,是解决“同逻辑、异类型”场景的经典范式。

















