java - 不可变类和子类

标签 java

我正在尝试了解可变/不可变类,我遇到了 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/

相关文章:

java - 如何配置 Inno Setup 以检查 Visual C++ Redistributable Packages

java - 在Java中你如何随机选择一个字母(a-z)?

java - 为什么 netty 日志不显示正确的类和包信息

java - 如何使用 Spring 验证密码

Java:使用 Java 8 API 对非连续字符串字符的子集进行排序的更快方法是什么

java - 将属性文件或 xml 文件中的属性值注入(inject) PreAuthorize(...) java 注释(未解决)

java - JPA 分页查询在每次后续调用中变慢

java - 带队列的信号量

java - 我们可以在同一阶段拥有多个 CXF 拦截器吗

java - 如何在java中检查Windows 7的位置