2013-05-19 12 views
30

私にゲッターやセッターを使用すると、原則としてhereが貼り付けられ、人は私にそれらを使わないように伝えます。 私は何をすべきか、何をすべきではないかをサイトが明確に説明していますが、尋ねるのではなく、私が伝えたいのは本当に説明していません。 getterとsetterを使う方がはるかに効率的です。getter/setter vs "tell、do not ask"を使う?


属性healtharmorでクラスWarriorを想像してみて:

class Warrior { 
    unsigned int m_health; 
    unsigned int m_armor; 
}; 

今、誰かが5秒のための彼の鎧を減らす特殊攻撃で私の戦士を攻撃します。

void Attacker::attack(Warrior *target) 
{ 
    target->setHealth(target->getHealth() - m_damage); 
    target->setArmor(target->getArmor() - 20); 
    // wait 5 seconds 
    target->setArmor(target->getArmor() + 20); 
} 

で(私が間違っているなら、私を修正)、それは次のようになり原理を聞かないで、言う:

void Attacker::attack(Warrior *target) 
{ 
    target->hurt(m_damage); 
    target->reduceArmor(20); 
    // wait 5 seconds 
    target->increaseArmor(20); 
} 

今セッターのそれはこのようになりますを使用して2番目は明らかに良く見えますが、私はこれの本当の利点を見つけることができません。 同じ方法(increase/decreaseset/get)が必要です。依頼する必要があるかどうか尋ねるメリットがありません。 たとえば、戦士の健康状態を100に設定するにはどうすればよいですか? healまたはhurtのどちらを使用すべきか、どの程度の健康を傷つけたり傷つけたりする必要があるかを理解していますか?

また、私はセッターとゲッタが世界中の最高のプログラマによって使用されているのを見ています。 ほとんどのAPIは、それを使用し、それは、STD libにすべての時間を使用さ​​れています:

for (i = 0; i < vector.size(); i++) { 
    my_func(i); 
} 
// vs. 
vector.execForElements(my_func); 

を私は持っている場合かに、ではない、私は1つの記事に関する占いをリンクを求めてここの人々を信じるかどうかを決定します成功した多くのお金と作業プログラムを作った大企業(リンゴ、マイクロソフト、アンドロイド、ゲームのほとんどなど)の90%を信じていると私はちょっと理解できないのです。なぜかは、は良い原則であると尋ねる。

getterやsetterですべてが簡単に見えるようになったら、どうすればいいですか?

+0

hp_reductionリストとarmor_reductionリストを使用すると、単一のhpまたはarmor_reductionリストを使用することができます。複数の敵が同じ犠牲者に当たったとき、複数のスレッドが健康と鎧のために同じ変数にアクセスするため、 。スレッドで5秒待っていませんか?どのようにして正確に5秒待つことができますか?タスクスケジューラも必要な場合があります。 –

+7

@huseyintugrulbuyukisikありがとうございますが、ここで働くゲームをコーディングしようとはしていません。単純な例だった –

+0

次に、最も単純な割り当て操作を行うことができます。戦士.HP- = 5; –

答えて

32

あなたは依然として同じ量のメソッド(増減vsset/get)が必要であり、依頼する必要があるかどうかを尋ねるメリットがありません。

あなたは間違っています。ポイントは、getVariablesetVariableを意味のある操作、例えばinflictDamageに置き換えることです。 getVariableincreaseVariableに置き換えると、ゲッターとセッターのあいまいな名前が異なります。

どこがこの問題ですか。例えば、防具と体力を別々に追跡するためにセッター/ゲッターを用意する必要はありません。単一のinflictDamageは、ブロックして(そしてプロセスのシールドを傷つけて)クラスを処理してから、シールドが十分でない場合、またはアルゴリズムが要求している場合は、同時に、より複雑なロジックを単一の場所に追加することができます。

一時的にダメージを与える魔法の盾を追加しますあなたがゲッター/セッターを持っているならば、すべての攻撃者がそのようなアイテムを持っているかどうかを知る必要があります。同じロジックを複数の場所に適用して、同じ結果になることを願ってください。 のアプローチでは、攻撃者はまだ自分のダメージを把握してキャラクターに伝える必要があります。そのキャラクターは、アイテム全体にダメージがどのように広がっているか、それが他の方法でキャラクターに影響を与えるかどうかを調べることができます。

ゲームを複雑にして火の武器を追加すると、inflictFireDamage(または火災のダメージをinflictDamageの別の引数として渡すことができます)。 Warriorは、彼女が耐火呪文の影響を受けているかどうかを知ることができ、プログラム内の他のすべてのオブジェクトが自分の行動が他のものにどのように影響するかを把握するのではなく、火災のダメージを無視します。

+3

これは、ちょうど "Duh、それはより良いカプセル化を提供する"というより、* tell、* ask *の利点を実際に説明した唯一の補足的な答えでした。あなたは受け入れに値するのですが、答えに感謝します! :) –

2

そうだとしたら、なぜゲッターやセッターに気になるのですか?パブリックフィールドを持つことができます。

void Attacker::attack(Warrior *target) 
{ 
    target->health -= m_damage; 
    target->armor -= 20; 
    // wait 5 seconds 
    target->armor += 20; 
} 

理由はここでは簡単です。カプセル化。セッターとゲッタがあれば、それはパブリックフィールドより優れていません。ここでは構造体を作成しません。定義されたセマンティクスでプログラムの適切なメンバーを作成します。

記事を引用:

をここでの最大の危険は、オブジェクトからのデータを要求することにより、あなた はデータのみを取得しているということです。あなたはオブジェクトを取得していません - 大きな の意味ではありません。クエリから受け取ったものが構造的に(例えば、String)オブジェクト であっても、それはもはや意味的にオブジェクトではありません。 所有者オブジェクトとの関連付けが終了しました。 "RED"の内容の文字列がある場合は、文字列 を要求することはできません。それは所有者の姓ですか?車の色は? タコメータの現在の状態?オブジェクトはこれらのことを知っていますが、 データはありません。

ここにある記事では、「尋ねないでください」は、意味をなさないことを行うことができないため、ここでは良いと言います。

target->setHealth(target->getArmor() - m_damage); 

ここでは、鎧は健康に関して何も持っていないので、ここでは意味がありません。

また、ここではstdlibで間違っています。 Getterとsetterはstd::complexでのみ使用されています。その理由は、言語には機能が不足しているからです(C++には参照がありませんでした)。それは実際には反対です。 C++標準ライブラリはアルゴリズムの使用を奨励し、コンテナで行うことを指示します。

std::for_each(begin(v), end(v), my_func); 
std::copy(begin(v), end(v), begin(u)); 
+0

私は個人的に心配することなく、それを> 0に保つために 'health'を変更したいと思っています。 – chris

+0

カプセル化はまったく忘れてしまいます。理にかなって...ない。あなたは不変物をどうやって維持しますか? – syam

+0

@サイヤンそれは問題ではありません。それはただの精神的な質問だった。 (あなたはどうしますか?あなたはint型に類似した型に '健康 'の型を変えることができますが、別のことをします) – milleniumbug

1

コントロールが必要な場所を決めることができます。

たとえば、セッター/ゲッターの例では、呼び出し元は任意にウォリアーのヘルスを変更できます。せいぜい、あなたの設定者は、健康状態が有効であることを保証するために最大値と最小値を強制するかもしれません。しかし、「通知」フォームを使用する場合は、追加ルールを適用することができます。一度に一定量以上の損傷や癒しを許すことはできません。

このフォームを使用すると、Warriorのインターフェイスをより詳細に制御できます。許可されている操作を定義し、それらを呼び出すすべてのコードを書き換えることなく実装を変更できます。

+0

攻撃のヒットポイント値は攻撃機能にも保存できます。 –

+0

あなたはセッターでもこれをほとんど行うことができますか? –

0

私の見解では、両方のコードが同じことをしています。違いはそれぞれの表現力です。最初のもの(セッター、アナドゲッター)は、2番目のものより表現力があります(教えてください、don 'ask)。

あなたが尋ねるとき、あなたは決断を下すことは本当です。しかし、それはほとんどの時代には起こりません。場合によっては、単にオブジェクトの値を知りたい、または設定したいと思うことがあります。で言うことはできません。に質問しないでください。

もちろん、プログラムを作成するときは、オブジェクトの責任を定義し、これらの責任がオブジェクト内にのみ残っていることを確認して、アプリケーションのロジックをそこから排除することが重要です。これはすでにわかっていますが、オブジェクトの責任を問わない決定をする必要がある場合は、でどうすればいいのですか?と尋ねないでください。

は実際には、ゲッターとセッターが優先され、それはTELLのアイデアを見るのが一般的だが、それとともにを聞きません。言い換えれば、一部のAPIにはゲッターとセッターがあり、のメソッドには、アイデアを尋ねないでください。

関連する問題