简体   繁体   中英

Best Approch of Returning Value from 'getter' Method

'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:

  • Making Employee immutable, and
  • Giving 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:

  1. interface GraphicDesigner extends Employee
  2. 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.

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