gpt4 book ai didi

java - 不可变类和子类

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:05:19 27 4
gpt4 key购买 nike

我正在尝试了解可变/不可变类,我遇到了 this post

提供的部分答案是:

If you want to enforce immutability, you cannot have subclasses. See for example java.lang.String, which is a final class for this reason: To prevent people from subclassing String to make it mutable.

好的,我明白了,但是,你会如何处理这个问题。假设您的任务是创建 3 个 Employee 类:Accountant、ITDepartment 和 QualityAssurance。现在,您可以创建一个名为 Employee 的抽象类,该类具有可供所有人共享的通用方法(员工 ID、姓名、薪水等),但是,您的类不再是不可变的。

使用Java,你会如何解决这个问题?您会创建 3 个类,使它们成为最终类,并且不实现抽象方法吗? (所以,没有任何子类)或者你会使用一个接口(interface),只提供 getters 吗?

最佳答案

If you want to enforce immutability, you cannot have subclasses.

这几乎是正确的,但不完全正确。重申一下:

If you want to enforce immutability, you must ensure that all sub-classes are immutable.

允许子类化的问题在于,通常任何可以编写类的人都可以对任何公共(public)非最终类进行子类化。

但是所有子类都必须调用其父类(super class)的构造函数之一。包私有(private)构造函数只能由同一包中的子类调用。

如果你seal packages为了控制包中的类,您可以限制子类化。首先定义一个你想子类化的类:

public abstract class ImmutableBaseClass {
ImmutableBaseClass(...) {
...
}
}

由于所有子类都必须访问 super 构造函数,因此您可以确保您定义的包中的所有子类都遵循不可变规则。

public final class ImmutableConcreteClass extends ImmutableBaseClass {
public ImmutableConcreteClass(...) {
super(...);
}
}

要将此应用于您的示例,

public abstract class Employee {
private final Id id;
private final Name name;

// Package private constructor in sub-classable class.
Employee(Id id, Name name, ...) {
// Defensively copy as necessary.
}
}

public final class Accountant extends Employee {
// Public constructos allowed in final sub-classes.
public Accountant(Id id, Name name, ...) {
super(id, name, ...); // Call to super works from same package.
}
}

public final class ITWorker extends Employee {
// Ditto.
public ITWorker(Id id, Name name, ...) {
super(id, name, ...);
}
}

关于java - 不可变类和子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31214446/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com