使用getter和setter(只获取和设置)而不是简单地为这些变量使用公共字段有什么好处?

如果getter和setter所做的不仅仅是简单的get/set,我可以很快地解决这个问题,但我不是100%清楚如何做到:

public String foo;

比:

private String foo;
public void setFoo(String foo) { this.foo = foo; }
public String getFoo() { return foo; }

而前者需要的样板代码要少得多。


当前回答

我知道现在有点晚了,但我想有些人对表演感兴趣。

我做了一个性能测试。我写了一个类“NumberHolder”,它包含一个整数。您可以使用getter方法读取该IntegeranInstance.getNumber()或通过使用anInstance.number直接访问数字。我的程序通过两种方式读取数字1000000000次。该过程重复五次,并打印时间。我得到了以下结果:

Time 1: 953ms, Time 2: 741ms
Time 1: 655ms, Time 2: 743ms
Time 1: 656ms, Time 2: 634ms
Time 1: 637ms, Time 2: 629ms
Time 1: 633ms, Time 2: 625ms

(时间1是直接方式,时间2是吸气方式)

你看,吸气器(几乎)总是快一点。然后我尝试了不同次数的循环。我用了1000万和10万,而不是100万。结果:

1000万次循环:

Time 1: 6382ms, Time 2: 6351ms
Time 1: 6363ms, Time 2: 6351ms
Time 1: 6350ms, Time 2: 6363ms
Time 1: 6353ms, Time 2: 6357ms
Time 1: 6348ms, Time 2: 6354ms

1000万次循环,时间几乎相同。以下是10万(10万)个循环:

Time 1: 77ms, Time 2: 73ms
Time 1: 94ms, Time 2: 65ms
Time 1: 67ms, Time 2: 63ms
Time 1: 65ms, Time 2: 65ms
Time 1: 66ms, Time 2: 63ms

同样,对于不同数量的循环,getter比常规方法快一点。我希望这对你有所帮助。

其他回答

到目前为止,我在回答中遗漏了一个方面,即访问规范:

对于成员,设置和获取只有一个访问规范对于setter和getter,您可以对其进行微调并单独定义

它可以用于延迟加载。假设所讨论的对象存储在数据库中,除非您需要,否则您不想获取它。如果该对象由getter检索,则内部对象可以为空,直到有人请求它,然后您可以在第一次调用getter时获取它。

我在交给我的一个项目中有一个基本页面类,它从几个不同的web服务调用加载一些数据,但这些web服务调用中的数据并不总是用于所有子页面。Web服务具有所有的优点,它开创了“慢”的新定义,因此如果不需要,您不想进行Web服务调用。

我从公共字段转到getter,现在getter检查缓存,如果缓存不存在,则调用web服务。因此,通过一点包装,许多web服务调用被阻止了。

因此,getter使我不必在每个子页面上找出我需要什么。如果我需要它,我打电话给吸气器,如果我还没有,它会帮我找到它。

    protected YourType _yourName = null;
    public YourType YourName{
      get
      {
        if (_yourName == null)
        {
          _yourName = new YourType();
          return _yourName;
        }
      }
    }

我只是想补充一点,即使有时它们对于变量/对象的封装和安全是必要的,如果我们想编写一个真正的面向对象的程序,那么我们需要停止过度使用附件,因为有时我们在不真正必要的情况下非常依赖它们,这几乎与我们将变量公开一样。

如果您想要一个只读变量,但不想让客户端改变访问它的方式,请尝试使用这个模板类:

template<typename MemberOfWhichClass, typename primative>                                       
class ReadOnly {
    friend MemberOfWhichClass;
public:
    template<typename number> inline bool   operator==(const number& y) const { return x == y; } 
    template<typename number> inline number operator+ (const number& y) const { return x + y; } 
    template<typename number> inline number operator- (const number& y) const { return x - y; } 
    template<typename number> inline number operator* (const number& y) const { return x * y; }  
    template<typename number> inline number operator/ (const number& y) const { return x / y; } 
    template<typename number> inline number operator<<(const number& y) const { return x << y; }
    template<typename number> inline number operator^(const number& y) const  { return x^y; }
    template<typename number> inline number operator~() const                 { return ~x; }
    template<typename number> inline operator number() const                  { return x; }
protected:
    template<typename number> inline number operator= (const number& y) { return x = y; }       
    template<typename number> inline number operator+=(const number& y) { return x += y; }      
    template<typename number> inline number operator-=(const number& y) { return x -= y; }      
    template<typename number> inline number operator*=(const number& y) { return x *= y; }      
    template<typename number> inline number operator/=(const number& y) { return x /= y; }      
    primative x;                                                                                
};      

示例用途:

class Foo {
public:
    ReadOnly<Foo, int> cantChangeMe;
};

记住,您还需要添加按位和一元运算符!这只是为了让你开始

从面向对象设计的角度来看,这两种选择都会削弱类的封装,从而对代码的维护造成损害。对于讨论,您可以查看这篇优秀的文章:http://typicalprogrammer.com/?p=23