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

时间:2020-03-05 18:37:16  来源:igfitidea点击:

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

我知道从对象外部我们应该使用getter / setter,但是从内部我们只需要这样做:

Java的:

String property = this.property;

PHP:

$property = $this->property;

还是你会做:

Java的:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

原谅我,如果我的Java有点过时了,距离我用Java编程已经一年了...

编辑:

似乎人们以为我只是在谈论私有或者受保护的变量/属性。当我学习面向对象时,我被教导即使每个属性都是公共的,也要对每个属性都使用吸气剂/设置器(实际上,我被告知永远不要公开任何变量/属性)。因此,我可能一开始就从一个错误的假设开始。似乎回答这个问题的人可能是在说我们应该拥有公共财产,而那些人不需要吸气剂和塞子,这与我所教的内容以及我所谈论的内容背道而驰,尽管也许需要讨论以下内容:出色地。不过,这可能是另一个问题的好话题...

解决方案:

这具有宗教上的战争潜力,但是在我看来,如果我们使用的是吸气剂/塞特剂,那么我们也应该在内部使用它,同时使用两者都会导致维护问题(例如,有人将代码添加到塞特剂中,这需要会在每次设置该属性时运行,并且在内部设置该属性而无需调用该setter)。

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

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

Am I just going overboard here?

可能 ;)

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

PHP:

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

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

然后从对象本身内部:

PHP:

$name = $this->_getName();

这样,我们仍然可以将第一个参数用于其他内容(例如,在此处发送一个标志,指示是否使用缓存的数据)。

好吧,似乎有了C3.0属性的默认实现,这个决定就由我们决定;我们必须使用(可能是私有的)属性设置器来设置属性。

我本人仅在不使用私有成员的情况下使用私有成员,否则会导致对象处于不太理想的状态,例如在初始化时或者在涉及缓存/延迟加载时。

正如一些评论中所述:有时应该,有时不应该。关于私有变量的重要之处在于,我们可以在更改某些内容时看到它们被使用的所有位置。如果getter / setter执行了我们需要的操作,请使用它。如果没关系,我们可以决定。

可能出现相反的情况,如果我们使用吸气剂/塞特而有人更改了吸气剂/塞特,则他们必须分析内部使用吸气剂和塞特器的所有位置,以查看是否弄乱了东西。

就个人而言,我觉得保持一致很重要。如果我们有getter和setter,请使用它们。我唯一直接访问字段的时间是访问器有很多开销。感觉好像我们在不必要地膨胀代码,但这无疑可以在将来节省很多麻烦。经典示例:

稍后,我们可能希望更改该字段的工作方式。也许应该即时计算,或者我们想为后备商店使用其他类型。如果我们直接访问属性,则这样的更改可能会使大量代码中断。

我可能是错误的,因为我是自动编辑的,但是我从不在Java类中使用公共属性,它们始终是私有的或者受保护的,因此外部代码必须由getter / setter进行访问。更好地用于维护/修改目的。对于内部类代码...如果getter方法很简单,我将直接使用该属性,但是我始终使用setter方法,因为如果愿意,我可以轻松地添加代码来引发事件。

我发现使用setters / getters使我的代码更易于阅读。我也喜欢其他类使用方法时提供的控件,并且如果我更改属性将存储的数据。

具有公共或者受保护属性的私有字段。对值的访问应通过属性,如果在方法中将多次使用它们,则应将其复制到局部变量。如果并且仅当我们对应用程序的其余部分进行了完全调整,精简和优化,以至于无法通过访问它们的关联属性来访问值成为瓶颈(而且我保证永远不会发生),即使我们开始考虑让属性以外的任何内容直接接触其后备变量。

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

如果用"纯粹主义者"的意思是"最封装",那么我通常将所有字段声明为私有,然后从类本身内部使用this.field,但是所有其他类(包括子类)都使用getter访问实例状态。

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

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

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

顺便说一句,我个人发现使用getter / setters可以使代码更易于阅读和以后进行调试。

" getters"和" setters"既好又好,我对此感到非常惊讶。我建议艾伦·霍鲁布(Allen Holub)的煽动性文章" Getters and Setters Are Evil"。诚然,标题是为了震撼价值,但作者提出了有效的观点。

本质上,如果每个私有字段都有" getters"和" setters",那么我们将使这些字段与公共字段一样好。我们将很难改变一个没有涟漪效应的私有字段的类型,以对每个调用该getter的类产生影响。

而且,从严格的面向对象的角度来看,对象应该响应与其(希望)单一职责相对应的消息(方法)。绝大多数的" getters"和" setters"对它们的组成对象没有意义;" Pen.dispenseInkOnto(Surface)"对我而言比" Pen.getColor()"更有意义。

Getter和Setter还鼓励类的用户向对象询问一些数据,执行计算,然后在该对象中设置其他值,这被称为过程编程。最好只是简单地告诉对象要做我们打算做的事情。也称为信息专家成语。

但是,在UI,持久性等层的边界上,getter和setter是必不可少的弊端。限制对类内部的访问,例如C ++的friend关键字,Java的程序包保护的访问,.NET的内部访问以及Friend Class Pattern,可以减少`getters''和setter方法对只有需要它们的人员的可见性。

纯粹的面向对象方法是避免两者,并通过使用"不要问"方法遵循Demeter法则。

与其获取紧密耦合这两个类的对象属性的值,不如将对象用作参数,例如

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

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

doSomethingWithProperty( this.daysPerWeek() ) ;

这些将使我们能够维护封装以及任何后置条件或者因变量。我们也可以使用setter方法来维护任何前提条件或者因变量,但是不要陷入为它们指定命名器的陷阱,使用成语时,请返回Hollywood原则进行命名。

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

可以将验证放入设置器(以及此方法的获取器)中。Intellisense可与显式方法配合使用毫无疑问,属性是只读,只写还是可读写检索虚拟属性(即,计算值)看起来与常规属性相同轻松设置一个从未在任何地方定义的对象属性,然后将其记录下来

这取决于。它比其他任何事情都更是样式问题,没有硬性规定。

我会说最好甚至在对象内使用访问器方法。这些是我马上想到的要点:

1)这样做的目的是为了保持与对象外部访问的一致性。

2)在某些情况下,这些访问器方法可能做的不仅仅是访问字段。他们可能会做一些额外的处理(虽然很少见)。如果是这种情况,那么直接访问该字段将导致我们错过额外的处理,并且如果在这些访问期间始终必须执行此处理,则程序可能会出错。