'将类字段/属性设为私有' - 是 OOP 中的最佳实践之一。要访问private
字段/属性,我们可以使用公共 getter 方法。但是根据这个博客,仅仅编写getter方法可能还不够(请参阅引用2)。它建议从 getter 方法返回字段/属性的克隆(如果是引用类型)。通过遵循这种方法,我们可以使字段/属性不可修改。请参阅下面的代码 -
public class Department{
Employee admin;
...
...
...
public Employee getAdmin(){
return admin.clone();
}
}
因此,从现在开始,如果我们不使用任何二传手,'admin'
就无法被外部世界修改。这种方法看起来很不错。但我几乎没有找到任何实现这种方法的代码。使用这种方法是否有任何缺点,可能会破坏使用这种方法的好处?
提前谢谢。
这种方法的主要缺点是每次获得对象时都需要制作克隆,这并不理想,因为理想情况下,您更喜欢轻量级的 getter。
有两种方法可以在不克隆的情况下实现类似的效果:
- 使
Employee
不可变,并且 - 为
Employee
提供不可变的接口
第一种方法是不言自明的,并且非常有效,但它并不总是实用的,尤其是在对象表示需要就地共享的状态的情况下。
第二种方法也很简单:与其Employee
成为一个类,不如让它成为一个只有getter的接口,创建一个实现Employee
的类EmployeeImpl
,并具有getter和setter,并在需要可变性时使用类。
public interface Employee {
String getFirstName();
String getLastName();
}
public class EmployeeImpl implements Employee {
private String firstName;
private String lastName;
public String getFirstName() {return firstName;}
public String getLastName() {return lastName;}
public void setFirstName(String name) {firstName = name;}
public void setLastName(String name) {lastName = name;}
}
这种方法可以通过投射到一个类来击败,但大多数时候它是可以的。
如果您处于敌对环境中,对实际对象的任何修改都将非常有害 - 例如,您正在为您的服务公开一些每个人都可以下载和使用的 API,您将不得不采用您描述的完整克隆方法。但是,这种情况相对较少。
注意:自从它首次发布以来,我更改了此答案。我建议的第一个解决方案存在继承问题,现在已经解决了。
克隆返回的对象通常是一个非常糟糕的选择。除非对象非常简单,或者您的应用程序不是很复杂,否则所有这些克隆很可能会带来巨大的开销。
针对特定情况的另一种方法是使用一个名为 Employee
的接口,该接口仅提供 getter。然后,还可以定义实现Employee
并提供资源库的 MutableEmployee
类。
interface Employee {
public String getName();
public float getSalary();
}
class MutableEmployee implements Employee {
private String name;
private float salary;
@Override
public String getName() {
return name;
}
@Override
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
super.salary = salary;
}
public void setName(String name) {
super.name = name;
}
}
然后,您的Department
类将像这样修改:
class Department {
private MutableEmployee admin;
public Employee getAdmin() {
return (Employee) admin;
}
public MutableEmployee getMutableAdmin() {
return admin;
}
}
定义MutableEmployee
的子类
当你想创建一个MutableEmployee
的子类时,比如MutableGraphicDesigner
,你需要定义以下内容:
-
interface GraphicDesigner extends Employee
-
class MutableGraphicDesigner extends MutableEmployee implements GraphicDesigner