简体   繁体   English

从“ getter”方法获得价值的最佳方法

[英]Best Approch of Returning Value from 'getter' Method

'Making the class field/property private' - is one of the best practice in OOP. “将类字段/属性设为私有” -是OOP中的最佳做法之一。 To access the private field/property we can use public getter method. 要访问private字段/属性,我们可以使用公共getter方法。 But only writing the getter method may not enough according to this blog(Please see Quote 2) . 但是根据此博客,仅编写getter方法可能不够用(请参阅Quote 2) It suggests returning a clone of the field/property (if it is a reference type) from the getter method. 它建议从getter方法返回字段/属性的副本(如果它是引用类型)。 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 . 因此,从现在开始,如果我们不使用任何setter,那么'admin'将无法被外部世界修改。 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 使Employee一成不变,并且
  • Giving Employee an immutable interface Employee一个不变的界面

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. 第二种方法也很简单:而不是让Employee一类,使其与干将只有一个接口,使类EmployeeImpl实现Employee ,并有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;}
}

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. 如果您处于敌对环境中,对实际对象的任何修改都是极其有害的-例如,您正在公开一些可供所有人下载和使用的服务API,则必须采用您描述的完整克隆方法。 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. 针对您的特定情况的替代方法是拥有一个名为Employee的接口,该接口仅提供获取器。 You can then also define the MutableEmployee class that implements Employee and also offers setters. 然后,您还可以定义实现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;
    }
}

Your Department class would then modified like this: 然后,您的Department类将进行如下修改:

class Department {
    private MutableEmployee admin;

    public Employee getAdmin() {
        return (Employee) admin;
    }

    public MutableEmployee getMutableAdmin() {
        return admin;
    }
}

Defining subclasses of MutableEmployee 定义MutableEmployee子类

When you want to create a subclass of MutableEmployee , like MutableGraphicDesigner , you will need to define the following: 当您想要创建MutableEmployee的子类(如MutableGraphicDesigner ,需要定义以下内容:

  1. interface GraphicDesigner extends Employee
  2. class MutableGraphicDesigner extends MutableEmployee implements GraphicDesigner

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

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