オブジェクトメソッド内からオブジェクトプロパティにどのようにアクセスしますか?[閉まっている]


96

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

オブジェクトの外側からはゲッター/セッターを使用する必要があることは知っていますが、内側からは次のようにするだけです。

Java:

String property = this.property;

PHP:

$property = $this->property;

またはあなたはそうします:

Java:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

Javaが少しずれていても許してください。Javaでプログラミングしてから1年になります...

編集:

私がプライベートまたは保護された変数/プロパティのみについて話していると人々が想定しているようです。オブジェクト指向を知ったとき、それがパブリックであっても、すべてのプロパティにゲッター/セッターを使用するように教えられました(実際、変数/プロパティをパブリックにしないように言われました)。それで、私は最初から間違った仮定から始めるかもしれません。この質問に答える人々はおそらくあなたは公共の財産を持っているべきであり、それらはゲッターとセッターを必要としないと言っているようです上手。それはおそらく別の質問に適したトピックでしょう...

回答:


62

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


プロパティの値を設定する以外に、セッターでは他に何もしていません。Javaでの誤った使用例です。
euphoria83

1
@ euphoria83多分、しかしそれはそれが起こることを排除するものではありません。
Greg Hurlman、2010

私は元の答えに同意します。ただし、クラスまたはオブジェクト内でプライベートなものを設定または取得する場合は、コードが失敗する原因となる何らかの方法で、getter / setterが循環的または冗長でないことを確認する必要があることを覚えておいてください。ゲッター/セッターを使用できない場合は、直接アクセスしてください。(例:ゲッター/セッターがセカンダリ(プライベート/保護)メソッドにアクセスしてデータを操作します。)
Rick Mac Gillis

43

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

後で、フィールドの動作方法を変更したい場合があります。多分それはその場で計算されるべきであるか、多分あなたはバッキングストアのために別のタイプを使いたいでしょう。プロパティに直接アクセスしている場合、そのような変更を行うと、1つのスウェルグループで非常に多くのコードが壊れる可能性があります。


26

私は感情が全会一致でgettersあり、セッターが上手で良いことにかなり驚いています。私はアレン・ホルブの焼夷弾記事「ゲッターとセッターは悪だ」を提案します。確かに、タイトルは衝撃の価値のためのものですが、著者は有効な点を述べています。

基本的に、あなたが持っている場合getterssettersそれぞれすべてのプライベートフィールドのために、あなたは、公共のように良いように、これらのフィールドを作っています。それを呼び出すすべてのクラスに波及効果を及ぼすことなく、プライベートフィールドのタイプを変更することは非常に困難ですgetter

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

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

ただし、ゲッターとセッターは、UI、永続性など、レイヤーの境界で必要な悪です。C ++のフレンドキーワード、Javaのパッケージ保護アクセス、.NETの内部アクセス、フレンドクラスパターンなどのクラスの内部への制限付きアクセスは、gettersそれらを必要とする人だけに可視性とセッターの可視性を減らすのに役立ちます。


19

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

ここで、名前が呼び出された回数をカウントするオブジェクトにプライベート整数カウンターがあるとします。無効なカウントが生成されるため、オブジェクト内からGetメソッドを使用したくない場合があります。


Studentオブジェクトがビジネス/ドメインオブジェクトの場合は、インフラストラクチャの詳細が混在しています。理想的には、ビジネス/ドメインオブジェクトはビジネス/ドメインロジックのみに関係する必要があります。
moffdub 2008

次のようなゲッターに何らかのブール値を追加するとどうなるでしょうか。PHP:public function getName($ outsideCall = true){if($ outsideCall){$ this-> incrementNameCalled(); } $ this-> nameを返します。次に、オブジェクト自体の中からget nameを呼び出した場合、次のように増加しないようにすることができます。PHP:$ name = $ this-> getName(false); ここで船外に行きますか?
cmcculloh

14

PHPは、魔法のメソッド__getやを含む、これを処理する無数の方法を提供します__setが、私は明示的なゲッターとセッターを好みます。理由は次のとおりです。

  1. 検証はセッター(およびその問題のゲッター)に配置できます
  2. Intellisenseは明示的なメソッドで動作します
  3. プロパティが読み取り専用か、書き込み専用か、読み書き可能かは問題ありません
  4. 仮想プロパティ(つまり、計算値)の取得は、通常のプロパティと同じように見えます
  5. 実際にはどこにも定義されていないオブジェクトプロパティを簡単に設定できます。

13

ここで船外に行きますか?

おそらく;)

別のアプローチは、private / protectedメソッドを使用して実際に取得(caching / db / etc)を行い、パブリックラッパーでカウントをインクリメントすることです。

PHP:

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

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

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

PHP:

$name = $this->_getName();

この方法でも、最初の引数を他の何かに使用できます(キャッシュされたデータを使用するかどうかのフラグを送信するなど)。


12

ここでポイントを逃しているに違いありませんが、なぜオブジェクト内のゲッターを使用してそのオブジェクトのプロパティにアクセスするのですか?

これを結論に導くと、ゲッターはゲッターを呼び出す必要があり、ゲッターはゲッターを呼び出す必要があります。

したがって、オブジェクトメソッド内でプロパティに直接アクセスすると、特にそのオブジェクト内の別のメソッドを呼び出す(とにかくプロパティに直接アクセスしてから返すだけである)と見なすのは、無意味で無駄な作業です(または質問を誤解しました)。 )。


私はあなたがコメントしなければならなかったのと同じ必要性に駆り立てられました...そして、それは閉じられていなかったと答えられました;)
Egg Vans

8

純粋なOOの方法は、両方を回避し、Tell Do n't Askアプローチを使用してデメテル法則に従うことです。

2つのクラスを密結合するオブジェクトのプロパティの値を取得する代わりに、オブジェクトをパラメーターとして使用します。

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

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

  doSomethingWithProperty( this.daysPerWeek() ) ;

これらにより、カプセル化と、事後条件または従属不変量を維持できます。また、セッターメソッドを使用して、前提条件や従属不変式を維持することもできますが、セッターに名前を付けるという罠に陥らず、イディオムを使用する場合はハリウッド原則に戻って名前を付けてください。


8

オブジェクト内でも、アクセサメソッドを使用することをお勧めします。すぐに頭に浮かぶポイントは次のとおりです。

  1. これは、オブジェクトの外部から行われたアクセスとの一貫性を維持するために実行する必要があります。

  2. 場合によっては、これらのアクセサメソッドは、フィールドにアクセスするだけではありません。追加の処理を行っている可能性があります(ただし、これはまれです)。この場合、フィールドに直接アクセスすると、その追加処理が欠落していることを意味し、これらのアクセス中にこの処理を常に実行すると、プログラムが失敗する可能性があります。


8

「純粋な」による「最もカプセル化」を意味する場合は、通常、すべてのフィールドをプライベートとして宣言し、クラス自体から「this.field」を使用します。サブクラスを含む他のクラスでは、ゲッターを使用してインスタンスの状態にアクセスします。


7

セッター/ゲッターを使用すると、コードが読みやすくなります。また、他のクラスがメソッドを使用し、プロパティが格納するデータを変更した場合に提供されるコントロールも気に入っています。


7

パブリックプロパティまたは保護プロパティを持つプライベートフィールド。値へのアクセスはプロパティを通過し、メソッドで複数回使用される場合はローカル変数にコピーする必要があります。アプリケーションの残りの部分が完全に微調整され、ロックアウトされており、関連付けられているプロパティを介して値にアクセスすることがボトルネックになっている場合にのみ最適化されている場合(そして、それが起こることは決してない、私は保証します)プロパティ以外のものを直接バッキング変数に直接触れさせることを検討する。

.NET開発者は、設計時にバッキング変数を見ることさえできないため、自動プロパティを使用してこれを強制できます。



7

私は自動学習なので間違っている可能性がありますが、Javaクラスでパブリックプロパティを使用することはありません。それらは常にプライベートまたは保護されているため、外部コードはゲッター/セッターからアクセスする必要があります。メンテナンス/変更の目的に適しています。そして、クラスコードの内側の場合... getterメソッドが簡単な場合は、プロパティを直接使用しますが、必要に応じてイベントを発生させるコードを簡単に追加できるため、常にsetterメソッドを使用します。


7

プロパティを編集しない場合は、get_property()別のオブジェクト内のMySQLiオブジェクトなどの特別な場合を除き、パブリックメソッドを使用します。この場合、プロパティをパブリックにしてとして参照し$obj->object_propertyます。

オブジェクト内では、常に$ this-> propertyです。


5

まあ、それはC#3.0プロパティのデフォルトの実装であるようで、決定はあなたのために行われます。(おそらくプライベート)プロパティセッターを使用してプロパティを設定する必要があります。

私は個人的には、メンバーのビハインドを使用しないと、初期化時やキャッシング/レイジーロードが関係している場合など、オブジェクトが望ましい状態ではなくなります。


5

私はcmccullohの答えが好きですが、最も正しいのはGreg Hurlmanの答えのようです。get-goから使い始めた場合や、getter / setterを使い慣れている場合は、常にgetter / setterを使用してください。

余談ですが、個人的には、getter / setterを使用すると、コードが読みやすくなり、後でデバッグしやすくなります。


4

コメントのいくつかで述べたように:する必要がある場合とそうでない場合があります。プライベート変数の優れた点は、何かを変更したときに、プライベート変数が使用されているすべての場所を確認できることです。ゲッター/セッターが必要なことを行う場合は、それを使用します。それが問題ではない場合は、決定します。

ゲッター/セッターを使用していて、誰かがゲッター/セッターを変更した場合、ゲッターとセッターが内部で使用されているすべての場所を分析して、何かが壊れているかどうかを確認する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.