可以使用非公开的 getter 和 setter 方法在 Java 中实现封装吗?

问题描述

据我了解,封装(在 Java 中)是将相关数据和方法以某种方式包装到对象中的机制,即数据对其他类隐藏,只能通过当前类的方法访问(又名数据隐藏),如果我错了,请纠正我。

在阅读一些教程时,我看到他们指定 getter 和 setter 方法应该是公开的。

我明白为什么它不应该是私有的,但为什么不保护或认?使用受保护或认的 getter 和 setter 方法是否仍算作封装?

解决方法

Java 中的封装是通过使类的字段 private 来实现的。通过使它们 protected 来实现较弱的封装。

Getter 和 setter 方法不实现封装。相反,它们为与封装数据的某些类型的交互提供了一种机制。如果数据未封装,则不需要 getter 和 setter 方法。因此,当然,您可以提供受保护或默认访问的 getter 和 setter,甚至私有的。或者根本没有。这完全取决于您希望您的课程向谁展示哪些功能。

将 getter 和 setter 公开是因为它们提供了使用类所必需的功能,而不是因为该级别的访问权限是封装的要求。

,

在阅读一些教程时,我看到他们指定 getter 和 setter 方法应该是公开的。

这通常在教程中完成,因为它更容易编写,同时还提供“某种面向对象的感觉”,因为您仍然可以使用 getter 和 setter 进行一些控制。

您也可以(不推荐)使用公共字段并完全省略 setter 和 getter:

public class Foo {
  public int i;
  public String s;
}

但是当使用 setter 时,您可以例如验证数据:

public class Foo {
  public void set(int temperature) {
    if(temperature < 273) throw new IllegalArgumentException();
    this.temperature = temperature;
  }
}

但是如果您需要一次验证多个值怎么办?使用 setter 只能始终验证当前值,但不能同时验证多个 setter 调用。这是公共二传手不好的一种情况。

另一件事是:面向对象的编程是关于说出名字的:setXYZ 你说得不多。例如,setTemperature 可能适合恒温器。但就是这样。也许你甚至有更高级的东西:setTemperatureLevel(值 1-5)然后设置内部 desiredTemperature,当这个值高于当前温度时,你想将 heater 设置为 { {1}}。

当使用简单的 setter 时,您无法控制所有这些步骤是否按正确顺序完成,或者是否跳过了某些步骤。但是使用 true 方法在类内部完成所有这些操作,方法调用者没有办法搞砸。

但当然,Java 世界中有些地方公共 setter 和 getter 非常方便:在许多框架中,例如将数据库映射到 DAO 或用于 JSON 反/序列化的 DTO,它使事情变得更容易。因为在这里它被用作读取和写入对象字段的约定。这些对象通常称为 JavaBeans

但是,当涉及到您的域对象时,我强烈建议将您不希望其他人访问和/或操作的所有内容保密。

,

访问者当然可以受到保护。例如,抽象基类可能会使用受保护的 getter 向子类公开一些内部状态,而该 getter 不是消费者应该使用的 API 的一部分。

也就是说,getter 和 setter 通常用于 JavaBeans 的上下文中,其中 getter 和 setter 定义对象的属性。如果它们不是公开可见的,那么虽然它们仍然提供封装,但它们不会用于特定目的。

您正在阅读的教程是从某个对象的用户(开发人员)的角度编写的。此类属性需要公开才能发挥作用,而且大多数属性访问器都是公开的。

,

封装是为了防止其他对象直接修改值。

如果您将 getter 和 setter 设为私有,则只有该类中的其他方法才能调用它们。这可能是因为您想验证该值,或者是因为您想确保支持多线程或其他一些问题。

如果您使它们受保护,那么继承和扩展类将能够调用它们,但没有其他类,甚至您的 main 方法也无法调用 getter 和 setter。

如果您只想公开值,则没有什么可以阻止您拥有受保护/私有的 setter 和公共 getter,或者根本没有 setter(您必须在另一种方法或构造函数中实例化该值)