简体   繁体   English

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

[英]Can encapsulation be achieved in Java with getter and setter methods that are not public?

As I've come to understand it, encapsulation (in Java) is the mechanism of wrapping related data and methods into objects in a way, that the data is hidden from other classes and only accessible through the methods of the current class (aka data hiding), correct me if I'm wrong.据我了解,封装(在 Java 中)是以某种方式将相关数据和方法包装到对象中的机制,即数据对其他类隐藏,只能通过当前 class(又名数据)的方法访问隐藏),如果我错了,请纠正我。

While reading some tutorials, I see that they specify that the getter and setter methods should be public.在阅读一些教程时,我看到他们指定 getter 和 setter 方法应该是公共的。

I get why it shouldn't be private but why not protected or default?我明白为什么它不应该是私有的,但为什么不保护或默认? Would the use of protected or default getter and setter methods still count as encapsulation?使用受保护的或默认的 getter 和 setter 方法仍然算作封装吗?

Encapsulation in Java is achieved by making a class's fields private . Java 中的封装是通过将类的字段设为private来实现的。 Weaker encapsulation is achieved by making them protected .通过使它们protected来实现较弱的封装。

Getter and setter methods do not implement encapsulation. Getter 和 setter 方法不实现封装。 Rather, they provide a mechanism for certain kinds of interaction with encapsulated data.相反,它们为与封装数据进行某些类型的交互提供了一种机制。 If the data were not encapsulated then getter and setter methods would not be required.如果未封装数据,则不需要 getter 和 setter 方法。 As such, sure, you can provide protected or default-access getters and setters, and even private ones.因此,当然,您可以提供受保护或默认访问的 getter 和 setter,甚至是私有的。 Or none at all.或者根本没有。 It's all a question of what features you want your class to expose to whom.这完全取决于您希望 class 向谁公开哪些功能。

When one makes getters and setters public it is because they provide features that are essential for use of the class, not because that level of access is a requirement for encapsulation.当人们公开 getter 和 setter 时,是因为它们提供了使用 class 所必需的功能,而不是因为这种访问级别是封装的要求。

While reading some tutorials, I see that they specify that the getter and setter methods should be public.在阅读一些教程时,我看到他们指定 getter 和 setter 方法应该是公共的。

That is often done in tutorials because it's easier to write, while also providing "some kind of object oriented feeling", because you still have some control using getters and setters.这通常在教程中完成,因为它更容易编写,同时还提供“某种面向 object 的感觉”,因为您仍然可以使用 getter 和 setter 进行一些控制。

You could (not recommended) also use public fields and omit the setters and getters completely:您也可以(不推荐)使用公共字段并完全省略 setter 和 getter:

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

But when using setters instead you can for example validate the data:但是,当使用 setter 时,您可以例如验证数据:

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

But what if you need to validate multiple values at once?但是,如果您需要一次验证多个值怎么办? Using a setter you can only always validate the current value, but you can't validate multiple setter calls together.使用 setter 只能始终验证当前值,但不能同时验证多个 setter 调用。 That's one scenario where public setters are bad.这是公共二传手不好的一种情况。

The other thing is: Object oriented programming is much about telling names: setXYZ doesn't you tell much.另一件事是:Object 面向编程主要是讲名字: setXYZ你讲的不多。 For example setTemperature might be fine for a thermostat.例如setTemperature可能适用于恒温器。 But that's it.但就是这样。 Maybe you even got something more advanced: setTemperatureLevel (values 1-5) which then sets the internal desiredTemperature and when this value is higher than the current temperature you want to set heater to true .也许你甚至得到了更高级的东西: setTemperatureLevel (values 1-5) 然后设置内部的desiredTemperature并且当这个值高于你想要设置heater的当前温度时true

When using simple setters, you have no control if all those steps are done in the right order, or if maybe some step was skipped.使用简单的设置器时,您无法控制是否所有这些步骤都以正确的顺序完成,或者是否跳过了某些步骤。 But using a setLevel method that does all of that inside the class, there's no way to screw up for the method caller.但是使用在 class 内完成所有这些操作的setLevel方法,没有办法搞砸方法调用者。

But of course there are places in the Java world where those public setters and getters are quite handy: In a lot of frameworks, like something for mapping database to DAOs, or DTOs for JSON de/serialization, it makes things easier.但当然,在 Java 世界中的某些地方,这些公共 setter 和 getter 非常方便:在许多框架中,例如将数据库映射到 DAO 或 JSON 反序列化的 DTO 的东西,它使事情变得更容易。 Because here it's used as a convention for reading and writing the fields of an object.因为在这里它被用作读取和写入 object 字段的约定 Those objects are often referred to as JavaBeans .这些对象通常称为JavaBeans

But when it comes to your domain objects, I highly recommend to keep everything private you don't want others to access and/or manipulate.但是当涉及到您的域对象时,我强烈建议您将不希望其他人访问和/或操纵的所有内容保密。

Accessors certainly can be protected.访问者当然可以受到保护。 For example, an abstract base class might expose some internal state to subclasses by using a protected getter that isn't part of the API that consumers are supposed to use.例如,抽象基 class 可能会通过使用不属于消费者应该使用的 API 的受保护 getter 将一些内部 state 暴露给子类。

That said, getters and setters are normally used in the context of JavaBeans , where the getters and setters define the properties of the object.也就是说,getter 和 setter 通常在JavaBeans的上下文中使用,其中 getter 和 setter定义了 object 的属性。 If they're not publicly visible, then while they do still provide encapsulation, they don't serve that particular purpose.如果它们不是公开可见的,那么虽然它们仍然提供封装,但它们不服务于特定目的。

The tutorials you are reading are written from the perspective of the user (who is a developer) of some object.您正在阅读的教程是从某些 object 的用户(开发人员)的角度编写的。 Such properties need to be public to do their job, and most property accessors are public.此类属性需要公开才能完成工作,并且大多数属性访问器都是公开的。

Encapsulation is meant to prevent other objects from modifying the values directly.封装是为了防止其他对象直接修改值。

If you make the getters and setters private, only other methods in that class will be able to call them.如果您将 getter 和 setter 设为私有,则只有 class 中的其他方法才能调用它们。 this may be becouse you want to validate the value, or because you want to ensure that there is support for multithreading, or some other issue.这可能是因为您想验证该值,或者因为您想确保支持多线程或其他一些问题。

If you make them protected, then inheiting and extending classes will be able to call them, nut no other classes, not even your main method would be able to call the getter and setter.如果你让它们受到保护,那么继承和扩展类将能够调用它们,但没有其他类,甚至你的main方法也不能调用 getter 和 setter。

If you want to expose the values only, nothing prevents you from having a protected/private setter, and a public getter, or no setter at all ( you would have to instantiate the value in another method, or in the constructor )如果您只想公开这些值,没有什么可以阻止您拥有受保护/私有 setter 和公共 getter,或者根本没有 setter(您必须在另一个方法或构造函数中实例化该值)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM