你将如何访问对象方法中的对象属性?

什么是“纯粹”或“正确”的方式来访问对象的方法,而不是一个getter / setter方法的对象的属性?

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

Java的:

String property = this.property; 

PHP:

 $property = $this->property; 

或者你会做:

Java的:

 String property = this.getProperty(); 

PHP:

 $property = $this->getProperty(); 

原谅我,如果我的Java是一点点closures,这是一年以来,我用Java编程…

编辑:

看来人们正在假设我只谈论私有或受保护的variables/属性。 当我学习OO时,我被教导使用getter / setter来处理每一个属性,即使这个属性是公开的(实际上我被告知从不公开任何variables/属性)。 所以,我可能会从一个错误的假设开始。 看来回答这个问题的人可能就是说你应该有公共财产,那些不需要得到的人,那些违背了我所教导的和我在谈论的东西,虽然也许这需要被讨论为好。 这可能是一个不同的问题,虽然好主题…

这具有宗教战争的潜力,但在我看来,如果你使用getter / setter,你也应该在内部使用它 – 使用两者都会导致维护问题(例如有人向需要的setter添加代码在每次设置属性时运行,并且在内部设置该属性而不调用该设置器)。

就个人而言,我觉得保持一致是很重要的。 如果你有吸气剂和吸附剂,使用它们。 我唯一直接访问字段的时候是访问者有很多开销。 这可能会让你觉得不必要地膨胀了你的代码,但是将来肯定可以节省很多的头痛。 经典的例子:

稍后,您可能希望改变该领域的工作方式。 也许它应该被即时计算,或者您可能想要使用不同types的后备商店。 如果你是直接访问属性,像这样的变化可以打破一个膨胀foop很多代码。

我相当惊讶的是, getters者和安定者的情绪如何一致好。 我build议艾伦霍勒布“ 吸气和安装者是邪恶的 ”燃烧的文章。 当然,标题是冲击价值,但作者提出了有效的观点。

从本质上讲,如果每个私人领域都有getterssetters ,那么你就是把这些领域和公共领域做的一样好。 你会非常困难的把一个私有领域的types改变成没有涟漪效应的每一个调用这个getter类。

此外,从严格的OO观点来看,对象应该回应与其(希望)单一责任相对应的消息(方法)。 绝大多数的gettersgetters setters对他们的构成物体是没有意义的; Pen.dispenseInkOnto(Surface)Pen.getColor()更有意义。

吸气师和制定者也鼓励class级的用户向对象询问一些数据,进行计算,然后在对象中设置一些其他的值,也就是程序编程。 你最好只是简单地告诉对象去做你将要做的事情。 也被称为信息专家成语。

然而,吸气者和制定者是图层边界的必要罪恶 – UI,持久性等等。 对C ++的friend关键字,Java的包保护访问,.NET的内部访问以及Friend类模式等类内部的限制访问可以帮助您将获取者和设置者的可见性减less到只有需要他们的人。

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

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

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

  1. validation可以放置在setters(和getters)
  2. 智能感知使用明确的方法
  3. 毫无疑问,属性是只读,只写还是读写
  4. 检索虚拟属性(即计算值)看起来与常规属性相同
  5. 您可以轻松设置一个永远不会在任何地方实际定义的对象属性,然后将其logging在文档中

我只是在这里过度?

也许 ;)

另一种方法是利用私有/受保护的方法来实际执行获取(caching/数据库/等),并为其增加计数的公共包装:

PHP:

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

然后从对象本身:

PHP:

 $name = $this->_getName(); 

这样,你仍然可以使用第一个参数来做其他事情(比如发送一个标志来判断是否使用caching数据)。

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

得出这个结论后,吸气者应该调用一个吸气剂,它应该叫做吸气剂。

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

如果说“纯粹”,你的意思是“最封装”,那么我通常将所有的字段声明为私有的,然后在类本身中使用this.field,但是所有其他类(包括子类)使用getter访问实例状态。

我会说它更好地使用访问器方法,即使在对象内。 以下是我立即想到的几点:

1)为了保持与对象之外访问的一致性,应该这样做。

2)在某些情况下,这些访问方法可能不仅仅是访问该领域; 他们可以做一些额外的处理(尽pipe罕见)。 如果是这种情况,通过直接访问该字段,您将错过额外的处理,并且如果在这些访问期间总是要执行处理,则程序可能会出错

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

私人领域与公共或受保护的财产。 对值的访问应该通过属性,如果在方法中多次使用它们,则将其复制到局部variables中。 如果并且只有当你的应用程序的其余部分完全调整,摆脱了,否则优化到哪里访问价值通过他们的assosciated财产已经成为一个瓶颈(这将永远不会发生,我保证),如果你甚至开始考虑让属性以外的任何东西直接触及其支持variables。

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

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

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

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

纯粹的OO方式是避免两者,并遵循Demeter法使用Tell Do not Ask方法。

而不是获取紧密耦合两个类的对象属性的值,例如,使用该对象作为参数

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

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

  doSomethingWithProperty( this.daysPerWeek() ) ; 

这些将允许您保持封装和任何后置条件或从属的不variables。 你也可以使用setter方法来维护任何前置条件或依赖不变式,但是不要陷入为setters命名的陷阱,在使用成语时要回到好莱坞原则来命名。

那么,似乎用C#3.0属性的默认实现,这个决定是为你而做的; 你必须使用(可能是私有的)属性设置器来设置属性。

我个人只有在不这样做的时候才使用私有成员,这会导致对象处于一个不太理想的状态,比如初始化或者涉及到caching/延迟加载时。

我可能是错误的,因为我autodidact,但我从来没有用户在我的爪哇公共属性,他们是总是私人或保护,以便外部代码必须访问getter / setters。 维护/修改的目的更好。 而对于内部类代码…如果getter方法是微不足道的,我直接使用属性,但我总是使用setter方法,因为如果我愿意,我可以很容易地添加代码来引发事件

我喜欢cmcculloh的答案,但似乎最正确的是格雷格·赫尔曼的答案。 如果您从getgo开始使用getter / setter,并且/或者习惯于使用getter / setter,则始终使用getter / setter。

另外,我个人发现使用getter / setter可以使代码更容易阅读和稍后debugging。

正如一些评论所述:有时你应该,有时你不应该。 关于私有variables的很大一部分是,当你改变某些东西的时候你可以看到所有的地方。 如果你的getter / setter做了你需要的东西,就用它。 如果没关系,你决定。

相反的情况是,如果你使用getter / setter,而有人改变了getter / setter,他们必须分析getter和setter在内部使用的所有地方,看看是否弄乱了某些东西。