封装与普通
Encapsulation Vs Plain
如果下面的代码会产生相同的结果,我为什么要使用封装?
The main benefit of encapsulation is the ability to modify our
implemented code without breaking the code of others who use our code.
但是我可以在不使用封装的情况下使用这个好处,对吗?因为每个物体的场都与彼此的场不同。
// Person.java
public class Person {
// Plain
public String name;
// Uses encapsulation
private String name2;
public void setName(String name2) {
this.name2 = name2;
}
public String getName() {
return name2;
}
}
// Main.java
public class Main() {
public static void main(String[] args) {
// Plain
Person person = new Person();
person.name = "Jordan";
System.out.println(person.name);
// Uses encapsulation
Person person2=new Person();
person2.setName("Jordan");
System.out.println(person2.getName());
}
}
- 通过提供 getter 和 setter,我们获得了隐藏实现的好处。例如您可以使用惰性初始化、代理等。
- 代码变得更易于维护,例如您可以轻松地在一处添加预检查和 post 检查(或验证)。如果您直接访问该变量,之后您需要在读取值时添加任何验证或一些默认行为,您将不得不在多个地方更改它。
- 通过 getter 和 setter,您可以获得多态性的好处。例如如果您不想在扩展版本中更改变量的值,反之亦然,您可以简单地抛出异常。
从调试的角度:
- 提供访问或更新变量值的代码行的隔离。 (可以用来查参考资料)
- 有时候,我们需要知道变量的值在哪里改变了。您可以放置调试指针或记录器来调查它。
封装是使 class 中的字段成为私有字段并通过 public 方法提供对字段的访问的技术。
public class Person {
private String name;
private Date dob;
private transient Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public int getAge() {
if (age == null) {
Calendar dob_cal = Calendar.getInstance();
dob_cal.setTime(dob);
Calendar today = Calendar.getInstance();
age = today.get(Calendar.YEAR) - dob_cal.get(Calendar.YEAR);
if (today.get(Calendar.MONTH) < dob_cal.get(Calendar.MONTH)) {
age--;
} else if (today.get(Calendar.MONTH) == dob_cal.get(Calendar.MONTH)
&& today.get(Calendar.DAY_OF_MONTH) < dob_cal.get(Calendar.DAY_OF_MONTH)) {
age--;
}
}
return age;
}
}
方法getAge()
returns你这个人的年龄,你不需要关心它是如何实现的,你不需要计算class之外的年龄。
使用封装的一种方法是隐藏实现。例如,有时 getter 不是 getter。考虑像球体这样的形状,我不一定会将体积或表面积存储为变量,因为我可以随时计算它们。我仍然会调用成员函数 getVolume 和 getSurfaceArea。使用我的代码的人不需要知道我是计算值还是简单地存储值。通过公开我的变量,我将它们锁定在一个设计决策中,如果我改变我的实现,这个设计决策将不得不改变(或破坏)。通过隐藏实现,您只需要知道接口(不要与 Java 的 'interface' 混淆)它以这种方式保护每个人并使未来的更改变得更加容易。
需要注意的是,有些时候setters/getter没有用到,变量就暴露了。即使在 Java 中,有时不隐藏实例变量更有意义。
你的问题很有意思。我会尽力为您深入解答。
封装背后的主要思想是对其他用户隐藏数据及其实现细节。如果我们将一个数据成员设为 private,那么它只能在同一个 class 中访问。没有其他 class 可以直接访问该数据。
但是我们可以定义一个接口,即 public getter 和 setter 方法来更新来自其他 classes 的数据。这可确保 私有数据对其他人保持无法访问 ,并且只能通过您提供的 public 方法访问。
例如,您可能决定只为特定数据成员提供 getter 方法而不提供 setter 方法。这确保没有其他 class 可以以任何可能的方式更改或更新您的数据成员。如果他们想使用 getter 方法,他们只能获得该值。
这就是封装也被称为数据隐藏的原因。
例子
public class EncapsulationDemo{
private int ssn;
private String empName;
private int empAge;
//Getter and Setter methods
public int getEmpSSN(){
return ssn;
}
public String getEmpName(){
return empName;
}
public int getEmpAge(){
return empAge;
}
public void setEmpAge(int newValue){
empAge = newValue;
}
public void setEmpName(String newValue){
empName = newValue;
}
public void setEmpSSN(int newValue){
ssn = newValue;
}
}
public class EncapsTest{
public static void main(String args[]){
EncapsulationDemo obj = new EncapsulationDemo();
obj.setEmpName("Mario");
obj.setEmpAge(32);
obj.setEmpSSN(112233);
System.out.println("Employee Name: " + obj.getEmpName());
System.out.println("Employee SSN: " + obj.getEmpSSN());
System.out.println("Employee Age: " + obj.getEmpAge());
}
}
优势
1) 它为代码提供 灵活性 并使其 易于维护。 我们可以更改 getEmpName()
的实现或 setEmpName()
而不影响任何其他外部代码。
2) 我们可以使数据成员只读(通过只定义getters)或只写 (通过仅定义 setters)随时。
3) 其他用户不会知道幕后发生的事情。他们只会知道要更新数据,我们需要调用 setter 方法,要获取数据,我们需要调用 getter 方法。
如果下面的代码会产生相同的结果,我为什么要使用封装?
The main benefit of encapsulation is the ability to modify our implemented code without breaking the code of others who use our code.
但是我可以在不使用封装的情况下使用这个好处,对吗?因为每个物体的场都与彼此的场不同。
// Person.java
public class Person {
// Plain
public String name;
// Uses encapsulation
private String name2;
public void setName(String name2) {
this.name2 = name2;
}
public String getName() {
return name2;
}
}
// Main.java
public class Main() {
public static void main(String[] args) {
// Plain
Person person = new Person();
person.name = "Jordan";
System.out.println(person.name);
// Uses encapsulation
Person person2=new Person();
person2.setName("Jordan");
System.out.println(person2.getName());
}
}
- 通过提供 getter 和 setter,我们获得了隐藏实现的好处。例如您可以使用惰性初始化、代理等。
- 代码变得更易于维护,例如您可以轻松地在一处添加预检查和 post 检查(或验证)。如果您直接访问该变量,之后您需要在读取值时添加任何验证或一些默认行为,您将不得不在多个地方更改它。
- 通过 getter 和 setter,您可以获得多态性的好处。例如如果您不想在扩展版本中更改变量的值,反之亦然,您可以简单地抛出异常。
从调试的角度:
- 提供访问或更新变量值的代码行的隔离。 (可以用来查参考资料)
- 有时候,我们需要知道变量的值在哪里改变了。您可以放置调试指针或记录器来调查它。
封装是使 class 中的字段成为私有字段并通过 public 方法提供对字段的访问的技术。
public class Person {
private String name;
private Date dob;
private transient Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public int getAge() {
if (age == null) {
Calendar dob_cal = Calendar.getInstance();
dob_cal.setTime(dob);
Calendar today = Calendar.getInstance();
age = today.get(Calendar.YEAR) - dob_cal.get(Calendar.YEAR);
if (today.get(Calendar.MONTH) < dob_cal.get(Calendar.MONTH)) {
age--;
} else if (today.get(Calendar.MONTH) == dob_cal.get(Calendar.MONTH)
&& today.get(Calendar.DAY_OF_MONTH) < dob_cal.get(Calendar.DAY_OF_MONTH)) {
age--;
}
}
return age;
}
}
方法getAge()
returns你这个人的年龄,你不需要关心它是如何实现的,你不需要计算class之外的年龄。
使用封装的一种方法是隐藏实现。例如,有时 getter 不是 getter。考虑像球体这样的形状,我不一定会将体积或表面积存储为变量,因为我可以随时计算它们。我仍然会调用成员函数 getVolume 和 getSurfaceArea。使用我的代码的人不需要知道我是计算值还是简单地存储值。通过公开我的变量,我将它们锁定在一个设计决策中,如果我改变我的实现,这个设计决策将不得不改变(或破坏)。通过隐藏实现,您只需要知道接口(不要与 Java 的 'interface' 混淆)它以这种方式保护每个人并使未来的更改变得更加容易。
需要注意的是,有些时候setters/getter没有用到,变量就暴露了。即使在 Java 中,有时不隐藏实例变量更有意义。
你的问题很有意思。我会尽力为您深入解答。
封装背后的主要思想是对其他用户隐藏数据及其实现细节。如果我们将一个数据成员设为 private,那么它只能在同一个 class 中访问。没有其他 class 可以直接访问该数据。
但是我们可以定义一个接口,即 public getter 和 setter 方法来更新来自其他 classes 的数据。这可确保 私有数据对其他人保持无法访问 ,并且只能通过您提供的 public 方法访问。
例如,您可能决定只为特定数据成员提供 getter 方法而不提供 setter 方法。这确保没有其他 class 可以以任何可能的方式更改或更新您的数据成员。如果他们想使用 getter 方法,他们只能获得该值。
这就是封装也被称为数据隐藏的原因。
例子
public class EncapsulationDemo{
private int ssn;
private String empName;
private int empAge;
//Getter and Setter methods
public int getEmpSSN(){
return ssn;
}
public String getEmpName(){
return empName;
}
public int getEmpAge(){
return empAge;
}
public void setEmpAge(int newValue){
empAge = newValue;
}
public void setEmpName(String newValue){
empName = newValue;
}
public void setEmpSSN(int newValue){
ssn = newValue;
}
}
public class EncapsTest{
public static void main(String args[]){
EncapsulationDemo obj = new EncapsulationDemo();
obj.setEmpName("Mario");
obj.setEmpAge(32);
obj.setEmpSSN(112233);
System.out.println("Employee Name: " + obj.getEmpName());
System.out.println("Employee SSN: " + obj.getEmpSSN());
System.out.println("Employee Age: " + obj.getEmpAge());
}
}
优势
1) 它为代码提供 灵活性 并使其 易于维护。 我们可以更改 getEmpName()
的实现或 setEmpName()
而不影响任何其他外部代码。
2) 我们可以使数据成员只读(通过只定义getters)或只写 (通过仅定义 setters)随时。
3) 其他用户不会知道幕后发生的事情。他们只会知道要更新数据,我们需要调用 setter 方法,要获取数据,我们需要调用 getter 方法。