'Making the class field/property private' - is one of the best practice in OOP. To access the private
field/property we can use public getter method. But only writing the getter method may not enough according to this blog(Please see Quote 2) . It suggests returning a clone of the field/property (if it is a reference type) from the getter method. By following this approach we can make the field/property unmodifiable. Please see the code below -
public class Department{
Employee admin;
...
...
...
public Employee getAdmin(){
return admin.clone();
}
}
So from now the 'admin'
is unmodifiable by the outer world if we don't use any setter . This approach looks pretty nice. But I hardly found any code which implements this approach. Is there any drawbacks of using this approach which may defeats the benefit of using this approach?
Thanks in advance.
The main drawback to this approach is the need to make a clone every time you get an object, which is not ideal, because ideally you prefer your getter to be lightweight.
There are two approaches that achieve similar effect without cloning:
Employee
immutable, and Employee
an immutable interface The first approach is self-explanatory and is very efficient, but it is not always practical, especially in situations when your object represents state that needs to be shared in place.
The second approach is simple, too: rather than making Employee
a class, make it an interface with only getters, make a class EmployeeImpl
that implements Employee
, and has getters and setters, and use the class when you need mutability.
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;}
}
This approach can be defeated by casting to a class, but most of the time it is OK.
If you are in a hostile environment where any modification to the actual object would be extremely harmful - say, you are exposing some API for your service that everyone could download and use, you would have to go for the full clone approach that you have described. However, situations like this are relatively rare.
Note: I changed this answer since it was first posted. The first solution I suggested had problems with inheritance which are now solved.
Cloning the objects returned is, generally, a very bad option. Unless the objects are very simple, or unless your application is not very complex, all this cloning will very likely introduce a significant overhead.
An alternative for your specific case is to have an interface called Employee
that only offers getters. You can then also define the MutableEmployee
class that implements Employee
and also offers setters.
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;
}
}
Your Department
class would then modified like this:
class Department {
private MutableEmployee admin;
public Employee getAdmin() {
return (Employee) admin;
}
public MutableEmployee getMutableAdmin() {
return admin;
}
}
Defining subclasses of MutableEmployee
When you want to create a subclass of MutableEmployee
, like MutableGraphicDesigner
, you will need to define the following:
interface GraphicDesigner extends Employee
class MutableGraphicDesigner extends MutableEmployee implements GraphicDesigner
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.