web-dev-qa-db-ja.com

ゲッターメソッドとセッターメソッドを使用する必要がありますか?

わかりました、これは本当に私を悩ませています、そしてそれはすべてより効率的であるかより良いコードを書く特定の方法ではなく個人的な選択に帰着するものだと思い始めています:PHPプロジェクト?これまで読んだ答えはかなり矛盾しており、コンパイルされた言語ではないPHPに完全に適しているわけではありません。たとえば、この質問をスタックオーバーフローで取り上げます( " ゲッターとセッターを使用する理由 ?")。コード内でそれらを使用する必要がある理由については、いくつかの正当な理由が提示されていますが、すべての子のコメントには Accessors are evil と記載されており、回避する必要があります。 「コードをごまかす」ため、これらは完全に回避する必要があります。

私が得ているのは矛盾する答えだけで、解釈されたPHP環境に関連するものはありません。 PHP内で使用する必要がある理由/理由と、その決定の背後にある根拠について誰かが光を当てることはできますか?プロパティをプライベートまたは保護されたものとして単純に定義できるかどうかは本当に重要ですか?

カプセル化ゲッターとセッターの提供は笑えるほど薄い

...「sbi」から引用(ゲッターとセッターを使用する理由)

個人的に、私はまだ方法がわかりません:

Class Foo {
    public $bar;

    function setBarType($val) {
       $this->bar = $val;
    }
}

$fee = new Foo();
$fee->setBarType(42);

これより優れています:

Class Foo {
    public $bar;
}

$fee = new Foo();
$fee->bar = 42;
25

値の設定方法の実装が(dbに)変更された場合、呼び出し元を変更する必要がないためです。別の例として、値を設定する前に値のチェックを行う必要がある場合があります。

メソッドがあると、その変数の設定/取得をインターセプトすることができ、必要と思われないときにそれを行うと、コードがより変更しやすくなります。

プロパティゲッター

C#やJavaScriptの最近のバージョンなどの言語では、プロパティの読み取りと書き込みをインターセプトできるため、それをサポートする言語でプロパティを使用できます。

オブジェクトウォッチャー

一部の言語では、すべての JavaScriptのObject.watch 、または PHPの__get でアクセスできないプロパティの読み取り/設定をインターセプトできます。これにより、ゲッターとセッターを実装できますが、プロパティへのアクセスごとにオーバーヘッドが発生するため、パフォーマンスが低下します。この回答では、ゲッターとセッターに関するその他の問題について説明しています。 ベストプラクティス:PHPマジックメソッド__setおよび__get

ゲッターとセッターは問題ありませんが...

ボイラープレートのゲッターとセッターを作成するだけの方が優れていますが、パブリックプロパティとほとんど同じです。誰かがオブジェクトの状態を(特に複数のプロパティを使用して)変更できる場合は、うまくカプセル化されません。 http://cspray.github.io/2012/05/13/stop-calling-them-getters-setters.html

13
Juan Mendes

リンク先のブログ投稿は重要な文で始まります(強調が追加されています):

コード内のすべてのゲッターとセッターは、カプセル化の失敗の失敗を表し、不要な結合を作成します。

カプセル化は、オブジェクト指向プログラミングの最も重要なアイデアです。それは本質的に、クラスの中にきちんとラップすることによって、非表示の複雑さに要約されます。理想的な世界では、クラスを使用するときに、内部の仕組みや状態について何でもを知っている必要はありません。一部の人々(このブログの作成者のような)は、ゲッターとセッターを持つことは、クラスの内部についてすでにあまりにも多くの情報であると主張します。彼らの見解では、クラスには、オブジェクトに方法を通知できるメソッドのみが含まれている必要があります方法はそれを行うか、それがどのような状態にあるかを気にしないでください。セッターは「オブジェクトに何かをするように伝える」のではなく、外部からオブジェクトの状態をいじくります。

これを行う代わりに:

$a = myObject();

// Querying object state, making a decision outside the object, and changing its state
if ($a->getWarbleFizz() < 42) {
    $a->setYourWarbleFizzTo(42);
}

// Gee, I hope I made the right decision...
$a->nowDoSomethingUseful();

あなたはこのようなコードを書いているはずです:

$a = myObject(42);
$a->doStuff();

またはこれ:

$a = myObject();
$a->doStuff(42);

関連読書: 教えてください、尋ねないでください

17
Miklos Aubert

ゲッターとセッターを使用する大きな利点は、変更を加える必要があるときはいつでも、ゲッターとセッターを変更するだけでよいことです。

例を挙げて説明します。

protected $date;
public function getDate(){
    return $this->date;
}
public function setDate($date){
    $this->date = $date;
}

日付を常に1日ずつ増やす必要がある理由があると想像してください。クラスメンバーにアクセスしたプロジェクト全体を検索する必要があります。

ただし、ゲッターとセッターを使用することで、コードを次のように変更できます。

protected $date;
public function getDate(){
    return $this->date;
}
public function setDate($date){
    $date = new DateTime($date);
    $date->modify('+1 day');
    $this->date = $date;
}
8
NLZ

1つOOPプリンシペはカプセル化です。クラスは、このクラス内に含まれるすべての変数を担当します。

パブリック変数を設定することで、その原則を破っています。

アクセサー(セッター)を作成することで、クラスの外でその値が変更される機会を与えることで、その原則を間接的に破っています。

ゲッターの利点は、呼び出しメソッドがデータの取得方法を気にする必要がないことです。期待されるデータを取得することを知っているだけで、それだけです。ここでは、カプセル化の原則が尊重されています。

セッターの利点は、クラスが新しい値を適用する前にチェックする機会があることです。完璧な世界では、クラスはすべての変数を完全に管理できるため、アクセサは必要ありません。現実の世界では、値を設定したり、外部から取得したりする必要がある場合があります。

完璧な世界に近づくための最良の方法は、修正する必要があるごく少数の変数のみにアクセサを制限することです。可能であれば設定値を確認してください。

あなたの例については、phpスタックに1つのレベルを保存するため、2番目のソリューションの方が優れています。変数はとにかくパブリック(カプセル化されていない)であり、追加のチェックを実行しないため、アクセサーは役に立ちません。ただし、可能な場合は、アクセサを使用してデータを確認する必要があります。アプリケーションの他の場所でデータが必要ない場合は、アクセサを実行しないでください。

5
Atrakeur

選択はあなた次第です。 PHP考慮すべき5つのその他の重要な機能は、マジックゲッター/セッターです。

http://www.php.net/manual/en/language.oop5.overloading.php#object.sethttp://www.php.net/manual/en/ language.oop5.overloading.php#object.get

これの魔法は、次のようなことを行い、事前に変数を宣言しなくても、変数を取得/設定する場所を決定できることです。

Class Foo {
    private $data = array();

    function __set($name,$val) {
       $this->$data[$name] = $val;
    }
    function __get($name) {
       if (array_key_exists($name, $this->data)) {
        return $this->data[$name];
    }
    else {
        return null;
    }
}

これで、次のようなことが自動的に行われます。

$ fee = new Foo(); $ fee-> bar = 42;

4
Matt

タイプセーフではないPHPのような言語でゲッターとセッターを使用しない場合、オブジェクトのプロパティのタイプが正しいことをどのように確認しますか?

私はポイントを完全に逃しているかもしれませんが、オブジェクトの外部からプロパティにアクセスする必要がある場合、それはまだアクセサーを使用する最良のオプションだと思います...

また、Juon Mendesが言及しているように、一部の言語では、プロパティ自体が処理されているときにインターセプトすることを提供しています。 これはPHPにも導入される可能性があります

あなたは公開セッターと保護されたゲッターを持つこともできます:

class TimePeriod {
    protected $Seconds = 3600;

    public $Hours {
        get { return $this->Seconds / 3600; }
        set { $this->Seconds = $value * 3600; }
    }

    // This property is read only as there is no setter
    public $Minutes {
        get { return $this->Seconds / 60; }
    }

    /* public getter, protected setter */
    public $Milliseconds {
        get { return $this->Seconds * 1000; }
        protected set { $this->Seconds = $value / 1000; }
    }
}
4
NDM

ゲッターとセッターを使用したIMOは良い習慣であり、コードの可読性も向上します。設定中に値を確認することとは別に、別の例があります。uがgetMoviesList()を呼び出すかどうかを検討してください。このgetメソッドはとにかく実装でき、ローカルdbから映画リストを取得したり、オンラインWebサービスから取得したりできます。したがって、決定を行うコードは、おそらくこの関数内にあります。どこから電話をかけても、場所や方法は気にしません。 Uだけ映画リストを取得

2
Jazib