您将如何从对象方法中访问对象属性?

时间:2008-08-01 16:10:30

标签: java php oop theory

从不是getter / setter方法的对象方法中访问对象属性的“纯粹主义”或“正确”方法是什么?

我知道从对象外部你应该使用一个getter / setter,但是你会从内部做到:

爪哇:

String property = this.property;

PHP:

$property = $this->property;

或者你会这样做:

爪哇:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

请原谅我,如果我的Java有点偏离,那我用Java编程已经有一年...

修改

似乎人们假设我只讨论私有或受保护的变量/属性。当我学习OO时,我被教导为每个属性使用getter / setter,即使它是公开的(实际上我被告知永远不会公开任何变量/属性)。所以,我可能会从一开始的错误假设开始。似乎回答这个问题的人可能会说你应该拥有公共财产,并且那些不需要吸气剂和制定者,这与我所教的内容相违背,以及我所谈论的内容,尽管可能需要讨论好。虽然这可能是一个不同问题的好主题......

18 个答案:

答案 0 :(得分:60)

这具有宗教战争潜力,但在我看来,如果你使用的是吸气剂/定位器,你也应该在内部使用它 - 使用它们会导致维护问题(例如有人添加代码到每次设置属性时需要运行的setter,并且内部设置属性而没有调用setter。

答案 1 :(得分:41)

就个人而言,我觉得保持稳定非常重要。如果您有吸气剂和固定剂,请使用它们。我唯一一次直接访问字段是访问者有很多开销。可能感觉你不必要地膨胀你的代码,但它肯定会在将来节省很多麻烦。经典的例子:

稍后,您可能希望更改该字段的工作方式。也许它应该是即时计算的,或者您可能希望为后备存储使用不同的类型。如果您直接访问属性,那么这样的更改可能会破坏大量代码。

答案 2 :(得分:25)

我很惊讶getters的情绪是多么一致,而且制定者很好也很好。我建议Allen Holub“Getters And Setters Are Evil”的煽动性文章。当然,标题是为了震撼价值,但作者提出了有效的观点。

基本上,如果您对每个私有字段都有getterssetters,那么您将使这些字段与公共字段一样好。你会非常难以将没有涟漪效应的私有字段的类型更改为调用getter的每个类。

此外,从严格的OO角度来看,对象应该响应与其(希望)单一责任相对应的消息(方法)。绝大多数getterssetters对其构成对象没有意义; Pen.dispenseInkOnto(Surface)对我来说比Pen.getColor()更有意义。

Getters和setter还鼓励类的用户向对象询问一些数据,执行计算,然后在对象中设置一些其他值,更好地称为过程编程。你可以更好地告诉对象在第一时间做你想做的事情;也被称为Information Expert成语。

然而,Getters和setter在层的边界 - UI,持久性等等方面是必要的弊端。对类的内部的限制访问,例如C ++的friend关键字,Java的包保护访问,.NET的内部访问和Friend Class Pattern可以帮助您降低getters和setter的可见性,仅限于那些需要它们的人

答案 3 :(得分:18)

这取决于财产的使用方式。例如,假设您有一个具有name属性的student对象。如果尚未检索到名称,则可以使用Get方法从数据库中提取名称。这样就减少了对数据库的不必要调用。

现在假设你的对象中有一个私有整数计数器,用于计算名称被调用的次数。您可能不希望在对象内部使用Get方法,因为它会产生无效计数。

答案 4 :(得分:13)

PHP提供了无数种方法来处理这个问题,包括魔术方法__get__set,但我更喜欢显式的getter和setter。原因如下:

  1. 验证可以放置在setter(和getter)中
  2. Intellisense使用显式方法
  3. 毫无疑问,属性是只读,只写还是读写
  4. 检索虚拟属性(即计算值)与常规属性相同
  5. 您可以轻松设置一个从未在任何地方实际定义的对象属性,然后将其取消文档

答案 5 :(得分:12)

  

我刚刚过火了吗?

也许;)

另一种方法是利用私有/受保护的方法来实际获取(缓存/ db / etc),并使用公共包装器来增加计数:

PHP:

public function getName() {
    $this->incrementNameCalled();
    return $this->_getName();
}

protected function _getName() {
    return $this->name;
}

然后从对象内部开始:

PHP:

$name = $this->_getName();

通过这种方式,您仍然可以将第一个参数用于其他内容(例如,在此处发送是否使用缓存数据的标志)。

答案 6 :(得分:11)

我必须忽略这一点,为什么你会在对象中使用getter来访问该对象的属性?

得出结论,getter应该调用一个getter,它应该调用getter。

所以我说在一个对象方法中直接访问一个属性,特别是看到在该对象中调用另一个方法(它只是直接访问该属性然后返回它)只是一个毫无意义的,浪费的练习(或者我误解了这个问题。)

答案 7 :(得分:7)

如果用“purist”表示“大多数封装”,那么我通常将所有字段声明为私有,然后在类本身内使用this.field,但所有其他类(包括子类)使用getters访问实例状态

答案 8 :(得分:7)

纯粹的OO方式是避免这两种情况,并使用Law of Demeter方法关注Tell Don't Ask

不是获取对象属性的值,而是tightly couples这两个类,而是将对象用作参数,例如。

  doSomethingWithProperty() {
     doSomethingWith( this.property ) ;
  }

如果属性是本机类型,例如int,使用访问方法,将其命名为问题域而不是编程域。

  doSomethingWithProperty( this.daysPerWeek() ) ;

这些将允许您维护封装和任何后置条件或依赖不变量。你也可以使用setter方法来维护任何前置条件或依赖不变量,但不要陷入命名它们的设置者的陷阱,回到好莱坞原则来命名使用这个习语。

答案 9 :(得分:7)

我想说甚至在对象中使用访问器方法也更好。以下是我立即想到的要点:

1)应该保持与在对象之外进行访问的一致性。

2)在某些情况下,这些访问器方法可能不仅仅是访问该字段;他们可能会做一些额外的处理(尽管很少见)。如果是这种情况,通过直接访问该字段,您将错过额外的处理,如果在这些访问期间始终要完成此处理,您的程序可能会出错

答案 10 :(得分:6)

我发现使用setter / getters使我的代码更容易阅读。我也喜欢它在其他类使用方法时给出的控件,如果我更改属性将存储的数据。

答案 11 :(得分:6)

包含公共或受保护属性的私有字段。对值的访问应该遍历属性,如果它们将在方法中多次使用,则复制到局部变量。如果并且只有你的应用程序的其余部分如此完全调整,晃动,并且优化到通过他们的相关属性访问值的地方已成为瓶颈(并且这永远不会发生,我保证)你是否应该开始考虑让除了属性之外的任何东西直接触及它们的支持变量。

.NET开发人员可以使用自动属性来强制执行此操作,因为您甚至无法在设计时看到支持变量。

答案 12 :(得分:6)

如果我不编辑属性,我将使用get_property()公共方法,除非它是一个特殊的场合,例如另一个对象中的MySQLi对象,在这种情况下我只是公开属性并引用它为$obj->object_property

在对象内部,对我来说总是$ this->属性。

答案 13 :(得分:6)

我可能是错的,因为我是autodidact,但我从不在我的Java类中使用公共属性,它们总是私有或受保护,因此外部代码必须由getter / setter访问。它更适合维护/修改目的。对于内部类代码...如果getter方法很简单,我直接使用属性,但我总是使用setter方法,因为如果我愿意,我可以轻松地添加代码来触发事件。

答案 14 :(得分:6)

这取决于。这是一个风格问题,而不是其他任何事情,并没有硬性规则。

答案 15 :(得分:5)

我喜欢cmcculloh的答案,但似乎最正确的是Greg Hurlman的答案。如果您从getgo开始使用它们和/或习惯使用它们,请始终使用getter / setter。

另外,我个人发现使用getter / setter可以使代码更容易阅读并在以后进行调试。

答案 16 :(得分:5)

好吧,看来C#3.0属性的默认实现,决定是为你做的;您必须使用(可能是私有的)属性设置器来设置属性。

我个人只使用私有成员,如果不这样做会导致对象落入一个不太理想的状态,例如初始化或涉及缓存/延迟加载时。

答案 17 :(得分:4)

正如一些评论所述:有时你应该,有时你不应该。关于私有变量的重要部分是,当您更改某些内容时,您可以看到它们被使用的所有位置。如果你的getter / setter做了你需要的东西,请使用它。如果没关系,你决定。

相反的情况可能是,如果你使用getter / setter并且有人更改了getter / setter,他们必须分析所有的地方,getter和setter在内部使用,以查看它是否混淆了什么。