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

cmcculloh 86 php java theory oop

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

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

Java的:

String property = this.property;

PHP:

$property = $this->property;

或者你会这样做:

Java的:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

请原谅我,如果我的Java稍微关闭,那我用Java编程已经有一年...

编辑:

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

Greg Hurlman.. 60

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


MojoFilter.. 42

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

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


moffdub.. 25

我对这种情绪的一致程度感到非常惊讶,getters而且制定者很好也很好.我建议艾伦·霍鲁布的" 煽动者和刽子手是邪恶的 " 煽动性文章.当然,标题是冲击值,但作者提出了有效的观点.

从本质上讲,如果你拥有getterssetters为每一个私人领域,那么你就会把这些领域和公众一样好.你会非常难以将没有涟漪效应的私有字段的类型更改为每个调用它的类getter.

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

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

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


Shawn.. 19

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

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


pix0r.. 13

我刚刚离开这里吗?

也许 ;)

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

PHP:

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

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

然后从对象本身内部:

PHP:

$name = $this->_getName();

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


用户甲.. 13

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

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


Egg Vans.. 11

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

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

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


Allain Lalon.. 7

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


Martin Spame.. 7

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

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

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

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

  doSomethingWithProperty( this.daysPerWeek() ) ;

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


Aadith.. 7

我会说,即使在对象内使用访问器方法也更好.以下是我立即想到的要点:

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

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


Coincoin.. 6

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

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


Telcontar.. 6

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


Brendon-Van-.. 6

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


Mel.. 6

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

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


Ross.. 6

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

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


Steve McLeod.. 6

这取决于.它更像是一个风格问题,而且没有硬性规则.


svrist.. 5

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

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


用户甲.. 5

我喜欢cmcculloh的回答,但看起来最正确的是Greg Hurlman的回答.如果您从getgo开始使用它们和/或习惯使用它们,请始终使用getter/setter.

顺便说一句,我个人发现使用getter/setter可以使代码更容易阅读并在以后进行调试.