可以将最初作为子类对象创建的对象更改为另一个子类对象吗?

huangapple go评论76阅读模式
英文:

Is it possible to change an object which was originally created as a subclass object to another subclass object?

问题

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

如果我像这样创建一个对象:

Account account1 = new BasicAccount();

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

英文:

For example, I have a Class (Account) and 2 subclasses (BasicAccount and PremiumAccount).

If I create an object like this

Account account1 = new BasicAccount();  

Is it possible to change account1 subclass to PremiumAccount?

答案1

得分: 1

正如评论中所指出的,这从根本上是不可能的。

解决底层问题的实际方法是通过包信封-信件模式(也称为句柄-主体习语)。

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

至少,这看起来如下:

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); // 复制状态
    }

    // … 实现 Account 方法并转发到 `instance`。
}

然后您可以像这样使用它:

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

As noted in comments, that’s fundamentally not possible.

A practical solution to the underlying problem is via the envelope–letter pattern (also known as handle–body idiom).

That is, you create a wrapper class that implements the common interface and dispatches all methods to an instance variable which can be reassigned.

At minimum, this would look as follows:

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`.
}

Then you can use it like this:

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

</details>



huangapple
  • 本文由 发表于 2020年8月26日 22:16:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/63599605.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定