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

无需instanceof或强制转换,实现父类调用子类方法的类重构方案

无需强制转换调用子类独有方法的重构方案

针对你提出的Java类结构重构需求,以下是几种可行的实现方案,均避免使用instanceof或强制类型转换:

方案一:基于能力接口的适配模式

通过定义独立的能力接口,让子类按需实现,再在抽象父类中提供统一的能力获取方法,既保持父类的简洁性,又能灵活扩展子类能力。

代码实现

  1. 定义银行账户专属能力接口
public interface BankAccountCapability {
    String getAccountNumber();
    void setAccountNumber(String accountNumber);
}
  1. 修改抽象Account类,添加能力获取方法
public abstract class Account {
    private double balance;
    private String password;

    // 原有getter/setter方法
    public double getBalance() { return balance; }
    public void setBalance(double balance) { this.balance = balance; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }

    // 泛型方法,安全获取指定类型的能力
    @SuppressWarnings("unchecked")
    public <T> Optional<T> getCapability(Class<T> capabilityType) {
        if (capabilityType.isInstance(this)) {
            return Optional.of((T) this);
        }
        return Optional.empty();
    }
}
  1. 让BankAccount实现能力接口
public class BankAccount extends Account implements BankAccountCapability {
    private String accountNumber;

    @Override
    public String getAccountNumber() {
        return accountNumber;
    }

    @Override
    public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }
}
  1. WalletAccount保持原有结构即可
public class WalletAccount extends Account {
    // 钱包账户专属逻辑
}

调用示例

Account account = new BankAccount();
account.getCapability(BankAccountCapability.class)
        .ifPresent(cap -> cap.setAccountNumber("622848xxxxxx1234"));
account.getCapability(BankAccountCapability.class)
        .ifPresent(cap -> System.out.println("账户号:" + cap.getAccountNumber()));

优缺点

  • 优点:父类无需新增子类专属方法,符合单一职责原则;新增子类能力只需添加新接口,扩展性强。
  • 缺点:调用时需通过getCapability方法获取能力,写法比直接调用多一层包装。

方案二:抽象类新增默认方法

在抽象Account类中定义子类独有的方法默认实现,子类按需重写该方法,直接通过父类引用调用,完全匹配需求中的写法。

代码实现

  1. 修改抽象Account类,添加默认方法
public abstract class Account {
    private double balance;
    private String password;

    // 原有getter/setter方法
    public double getBalance() { return balance; }
    public void setBalance(double balance) { this.balance = balance; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }

    // 默认返回空Optional,避免空指针
    public Optional<String> getAccountNumber() {
        return Optional.empty();
    }

    // 默认抛出不支持操作异常,提示非法调用
    public void setAccountNumber(String accountNumber) {
        throw new UnsupportedOperationException("当前账户类型不支持设置账户号");
    }
}
  1. BankAccount重写方法
public class BankAccount extends Account {
    private String accountNumber;

    @Override
    public Optional<String> getAccountNumber() {
        return Optional.ofNullable(accountNumber);
    }

    @Override
    public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }
}

调用示例

Account account = new BankAccount();
account.setAccountNumber("622848xxxxxx1234");
account.getAccountNumber().ifPresent(num -> System.out.println("账户号:" + num));

优缺点

  • 优点:调用方式完全符合需求中的account.getAccountNumber()写法,直观简洁。
  • 缺点:抽象类会逐渐积累子类专属方法,违反单一职责原则;钱包账户调用该方法会抛出异常,需做好异常处理。

方案三:访问者模式

通过访问者模式分离数据结构和操作,针对不同类型的账户实现不同的访问逻辑,适合需要对不同账户类型执行多组操作的场景。

代码实现

  1. 定义访问者接口
public interface AccountVisitor {
    void visitBankAccount(BankAccount account);
    void visitWalletAccount(WalletAccount account);
}
  1. 修改抽象Account类,添加接受访问的方法
public abstract class Account {
    private double balance;
    private String password;

    // 原有getter/setter方法
    public double getBalance() { return balance; }
    public void setBalance(double balance) { this.balance = balance; }
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }

    public abstract void accept(AccountVisitor visitor);
}
  1. 子类实现accept方法
public class BankAccount extends Account {
    private String accountNumber;

    public String getAccountNumber() { return accountNumber; }
    public void setAccountNumber(String accountNumber) { this.accountNumber = accountNumber; }

    @Override
    public void accept(AccountVisitor visitor) {
        visitor.visitBankAccount(this);
    }
}

public class WalletAccount extends Account {
    @Override
    public void accept(AccountVisitor visitor) {
        visitor.visitWalletAccount(this);
    }
}
  1. 实现具体访问者(比如获取账户号的访问者)
public class AccountNumberVisitor implements AccountVisitor {
    private String accountNumber;

    @Override
    public void visitBankAccount(BankAccount account) {
        this.accountNumber = account.getAccountNumber();
    }

    @Override
    public void visitWalletAccount(WalletAccount account) {
        this.accountNumber = null; // 钱包账户无账户号
    }

    public String getAccountNumber() {
        return accountNumber;
    }
}

调用示例

Account account = new BankAccount();
((BankAccount) account).setAccountNumber("622848xxxxxx1234");
AccountNumberVisitor visitor = new AccountNumberVisitor();
account.accept(visitor);
System.out.println("账户号:" + visitor.getAccountNumber());

优缺点

  • 优点:操作与数据结构分离,新增操作只需添加新的访问者类,符合开闭原则。
  • 缺点:结构相对复杂,若新增账户类型需修改访问者接口,违反开闭原则;调用需借助访问者实例,写法不够直接。

内容的提问来源于stack exchange,提问作者Mohamed Amir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 09:40:35