【问题标题】:Is it possible to change an object which was originally created as a subclass object to another subclass object?是否可以将最初作为子类对象创建的对象更改为另一个子类对象?
【发布时间】:2020-08-26 14:16:02
【问题描述】:

例如,我有一个类(Account)和 2 个子类(BasicAccount 和 PremiumAccount)。

如果我创建这样的对象

Account account1 = new BasicAccount();  

是否可以将 account1 子类更改为 PremiumAccount?

【问题讨论】:

  • 您可以分配例如account1 = new PremiumAccount();但是没有办法将BasicAccount 的实例更改为PremiumAccount
  • 没有内置方法,必须编码。例如。 account1 = new PremiumAccount(account1) 如果您需要保留一些字段,请使用适当的构造函数。
  • 否:如果BasicAccountPremiumAccount 都是Account 的直接子类,那么BasicAccount 不是PremiumAccount。你可以构建一个PremiumAccount 来自一个BasicAccount
  • 如果帐户可以在功能上升级为高级帐户或从高级帐户降级,您可以考虑将高级帐户定义为您帐户的属性 (private boolean isPremium;) 而不是子类。
  • 这是一个像 state-pattern 或 decorator-pattern 这样的设计模式的用例,而不是继承。 “高级”或“基本”是帐户的状态,而不是更具体的类型。

标签: java class oop subclass


【解决方案1】:

正如 cmets 所述,这基本上是不可能的。

通过envelope–letter pattern(也称为handle-body idiom)可以解决根本问题。

也就是说,您创建一个包装类,它实现了公共接口并将所有方法分派给一个可以重新分配的实例变量。

至少应该如下所示:

class AccountWrapper implements Account {
    private Account instance;

    private AccountWrapper(Account instance) {
        this.instance = instance;
    }

    public static AccountWrapper createBasicAccount() {
        return new AccountWrapper(new BasicAccount());
    }

    public static AccountWrapper createPremiumAccount() {
        return new AccountWrapper(new PremiumAccount());
    }

    public void upgrade() {
        if (instance instanceof PremiumAccount) throw new InvalidStateException();
        this.instance = new PremiumAccount(instance); // copy state
    }

    // … implement Account methods and forward to `instance`.
}

那么你可以这样使用它:

final AccountWrapper account = AccountWrapper.createBasicAccount();
// …
account.upgrade();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-24
    • 2011-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多