86


5

getter / setterメソッドではないオブジェクトメソッド内からオブジェクトのプロパティにアクセスするための「純粋主義者」または「正しい」方法は何ですか?

オブジェクトの外側からgetter / setterを使うべきだと私は知っていますが、内側からはあなたがするだけです:

Java:

String property = this.property;

PHP:

$ property = $ this-> property;

それとも、

Java:

String property = this.getProperty();

PHP:

$ property = $ this-> getProperty();

私のJavaが少し遅れているのを許してください、私がJavaでプログラムしてから1年が経ちました…​

編集:

私が個人的な、または保護された変数/プロパティについてだけ話していると人々は想定しているようです。 オブジェクト指向を学んだとき、たとえそれが公開されていたとしても、すべてのプロパティに対してゲッター/セッターを使うように教えられました(そして実際には変数/プロパティを決して公開しないように言われました)。 だから、私は始めから誤った仮定から始めているかもしれません。 この質問に答える人々はあなたが公共の財産を持っているべきで、ゲッターやセッターを必要としないと言っているのかもしれませんが、それは私が教えたことや私が話していたことに反します。そうですね。 それはおそらく別の質問のための良いトピックです…​

18 Answer


60


これには宗教戦争の可能性がありますが、ゲッター/セッターを使用している場合は、内部でも使用する必要があります。両方を使用すると、メンテナンスの問題が発生します(例: 誰かが、そのプロパティが設定されるたびに実行する必要があるセッターにコードを追加し、そのプロパティはそのセッターが呼び出されることなく内部的に設定されています)。


42


個人的には、一貫性を保つことが重要だと思います。 ゲッターとセッターがある場合は、それらを使用してください。 フィールドに直接アクセスするのは、アクセサが多くのオーバーヘッドを抱えているときだけです。 不必要にコードを膨らませているように感じるかもしれませんが、将来的には頭痛の種を大幅に減らすことができます。 古典的な例:

後で、あなたはフィールドが機能する方法を変えることを望むかもしれません。 たぶんそれはオンザフライで計算されるべきであるか、あるいは多分あなたはバッキングストアのために異なるタイプを使用したいと思うでしょう。 あなたが直接プロパティにアクセスしているならば、そのような変更は1つのうねりのための膨大なコードを壊すことができます。


25


私は、「ゲッター」とセッターが素晴らしくて良いという感情が全会一致であることにかなり驚いています。 私はAllen Holubによる焼夷弾の記事「http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html [ゲッターとセッターは悪]]を提案します。 確かに、タイトルは衝撃的価値のためのものですが、作者は有効なポイントを作ります。

基本的に、すべてのプライベートフィールドに getters`と setters`があれば、それらのフィールドはpublicと同じくらい良いものになります。 その `getter`を呼び出すすべてのクラスに波及効果を与えずにプライベートフィールドの型を変更するのは非常に困難です。

さらに、厳密にオブジェクト指向の観点からすると、オブジェクトはそれらの(うまくいけば)単一の責任に対応するメッセージ(メソッド)に応答するべきです。 getters`と setters`の大多数はそれらの構成オブジェクトには意味がありません; `Pen.dispenseInkOnto(Surface)`は `Pen.getColor()`よりも私には意味があります。

ゲッターとセッターはまた、クラスのユーザーがオブジェクトにデータを要求し、計算を実行してから、オブジェクトに他の値を設定することを推奨します。これは手続き型プログラミングとしてよく知られています。 そもそも自分がやろうとしていたことを行うようにオブジェクトに指示するほうがよいでしょう。 Information Expertイディオムとしても知られています。

しかし、ゲッターとセッターはレイヤーの境界、つまりUI、永続性などにおいて必要な悪です。 Cのfriendキーワード、Javaのパッケージ保護アクセス、.NETの内部アクセス、http://moffdub.wordpress.com/2008/09/17/friend-classes-in-javaなど、クラスの内部へのアクセス制限-and-c-sharp / [Friend Class Pattern]は `getters`とsetterの可視性をそれらを必要とする人だけに減らすのに役立ちます。


19


プロパティの使い方によって異なります。 たとえば、nameプロパティを持つ学生オブジェクトがあるとします。 まだ取得されていない場合は、Getメソッドを使用してデータベースから名前を取得できます。 これにより、データベースへの不要な呼び出しを減らすことができます。

今、あなたはあなたのオブジェクトの中に名前が呼ばれた回数を数えるプライベート整数カウンタを持っているとしましょう。 無効なカウントを生成する可能性があるため、オブジェクトの内側からGetメソッドを使用したくない場合があります。


13


私はここに行き過ぎて行きますか?

おそらく;)

もう1つの方法は、private / protectedメソッドを実際に取得するために使用すること(caching / db / etc)と、それをカウントするためのパブリックラッパーです。

PHP:

パブリック関数getName(){$ this-> incrementNameCalled(); $ this  - > _ getName();を返します。 }

保護された関数_getName(){return $ this-> name; }

そしてオブジェクト自体の中から:

PHP:

$ name = $ this  - > _ getName();

このようにして、あなたはまだ他の何かのためにその最初の引数を使うことができます(おそらくここでキャッシュされたデータを使うべきかどうかに関するフラグを送ることのように)。


13


PHPはこれを処理するための無数の方法を提供しています。例えば、 get`や set`という魔法のメソッドがありますが、私は明示的なゲッターとセッターを好みます。 これが理由です:

  1. バリデーションはセッター(そしてそれに関するゲッター)に置くことができます

  2. Intellisenseは明示的な方法で動作します

  3. プロパティが読み取り専用、書き込み専用、または読み書き可能かどうかにかかわらず、問題はありません。

  4. 仮想プロパティ(つまり、計算値)の取得は同じように見えます 通常のプロパティとして

  5. 実際に定義されていないオブジェクトプロパティを簡単に設定できます どこでも、それは文書化されていません


11


私はここでポイントを逃しているにちがいありません、なぜあなたはそのオブジェクトの特性にアクセスするためにオブジェクトの中でゲッターを使うのですか?

これを結論として、ゲッターはゲッターを呼び出し、ゲッターはゲッターを呼び出すべきです。

したがって、オブジェクトメソッド内でプロパティに直接アクセスする、特にそのオブジェクト内の別のメソッドを呼び出すこと(これは単にプロパティに直接アクセスしてからそれを返す)は無意味で無駄な演習にすぎません(または質問を誤解しています) )


7


「純粋主義者」とは「ほとんどのカプセル化」を意味します。通常、私は自分のすべてのフィールドをプライベートとして宣言し、クラス自体の中からthis.fieldを使用しますが、サブクラスを含む他のすべてのクラスはゲッターを使用してインスタンス状態にアクセスします。


7


純粋主義者のOO方法は、 Tell Don’tを使用して、両方を避けて http://c2.com/cgi/wiki?TellDontAsk[Law of Demeterに従うことです。尋ねる]アプローチ。

https://stackoverflow.com/questions/2832017/what-is-the-difference- between-loose-coupling-and-tight-coupling-in-object-orien[tightly 2つのクラスを結合し、オブジェクトをパラメータとして使用します。

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

プロパティがネイティブ型の場合 int、アクセス方法を使用し、プログラミングドメインではなく問題ドメインに名前を付けます。

doSomethingWithProperty(this.daysPerWeek());

これらはあなたがカプセル化とどんな事後条件または従属不変式も維持することを可能にするでしょう。 setterメソッドを使って前提条件や依存する不変式を維持することもできますが、setterという名前を付けることの罠には陥らないでください。慣用句を使うときはHollywood Principleに戻って名前を付けてください。


7


オブジェクト内でもアクセサメソッドを使用する方が良いと思います。 すぐに私の頭に浮かぶポイントは次のとおりです。

1)オブジェクトの外部で行われたアクセスとの一貫性を保つために行われるべきです。

2)場合によっては、これらのアクセサメソッドはフィールドにアクセスするだけでは不十分です。彼らはいくつかの追加処理をしている可能性があります(それはまれですが)。 このような場合、フィールドに直接アクセスすることで、その追加の処理を見逃してしまい、この処理がこれらのアクセス中に常に行われることになっているとプログラムがうまくいかなくなる可能性があります。