最初に、パラダイムを明確にします。
- データ構造->適切に知識のある機能によって走査および操作できるメモリのレイアウト。
- オブジェクト->実装を隠し、通信可能なインターフェースを提供する自己完結型モジュール。
ゲッター/セッターはどこで便利ですか?
データ構造でゲッター/セッターは便利ですか?いや
データ構造は、一連の関数に共通して操作されるメモリレイアウト仕様です。
一般的に、古い新しい関数はすべて他の関数が理解できるようにデータ構造を操作し、操作できる場合、その関数はファミリに参加します。それ以外の場合、不正な機能とバグの原因となります。
誤解しないでください。スニッチ、ターンコート、および二重エージェントを含むデータ構造を巡って機能するいくつかの関数ファミリが存在する可能性があります。それぞれが独自のデータ構造を持っている場合は問題ありませんが、共有する場合は...いくつかの犯罪家族が政治に反対していると想像してみてください。
拡張機能ファミリが達成できる混乱を考えると、不正な機能がすべてを混乱させないようにデータ構造をエンコードする方法はありますか?はい、それらはオブジェクトと呼ばれます。
オブジェクトでゲッター/セッターは便利ですか?いや
データ構造をオブジェクトにラップすることの全体的な目的は、不正な機能が存在しないようにすることでした。関数がファミリーに参加したい場合は、最初に徹底的に吟味し、次にオブジェクトの一部にする必要がありました。
ゲッターとセッターのポイント/目的は、オブジェクトの外部の関数がオブジェクトのメモリレイアウトを直接変更できるようにすることです。それは悪党で許可するための開かれた扉のように聞こえます...
エッジケース
公共のゲッター/セッターが理にかなっている2つの状況があります。
- オブジェクト内のデータ構造の一部はオブジェクトによって管理されますが、オブジェクトによって制御されません。
- 一部の要素が実装オブジェクトを制御していないことが予想される、データ構造の高レベルの抽象化を記述するインターフェース。
コンテナとコンテナインターフェイスは、これら2つの状況の両方の完璧な例です。コンテナは、データ構造(リンクリスト、マップ、ツリー)を内部で管理しますが、特定の要素をすべておよびその他に制御します。インターフェイスはこれを抽象化し、実装を完全に無視し、期待のみを記述します。
残念ながら、多くの実装ではこれが間違っており、これらの種類のオブジェクトのインターフェースを定義して、実際のオブジェクトに直接アクセスできます。何かのようなもの:
interface Container<T>
{
typedef ...T... TRef; //<somehow make TRef to be a reference or pointer to the memory location of T
TRef item(int index);
}
これは壊れています。Containerの実装は、内部の制御を使用者に明示的に渡す必要があります。これがうまくいく可変値言語を見たことはまだありません(不変値セマンティクスを持つ言語は、データ破損の観点からは定義上問題ありませんが、必ずしもデータスパイの観点からではありません)。
コピーセマンティクスのみを使用するか、プロキシを使用して、ゲッター/セッターを改善/修正できます。
interface Proxy<T>
{
operator T(); //<returns a copy
... operator ->(); //<permits a function call to be forwarded to an element
Proxy<T> operator=(T); //< permits the specific element to be replaced/assigned by another T.
}
interface Container<T>
{
Proxy<T> item(int index);
T item(int index); //<When T is a copy of the original value.
void item(int index, T new_value); //<where new_value is used to replace the old value
}
おそらく、不正な機能はここで騒乱を起こす可能性があります(ほとんどの場合十分な労力で可能です)が、コピーセマンティクスやプロキシは多くのエラーの可能性を減らします。
- オーバーフロー
- アンダーフロー
- サブ要素との相互作用は型チェック/型チェック可能です(型を失う言語ではこれは恩恵です)
- 実際の要素は、メモリに常駐する場合としない場合があります。
プライベートゲッター/セッター
これは、型を直接操作するゲッターとセッターの最後の要塞です。実際、これらのゲッターとセッターではなく、アクセサーとマニピュレーターとも呼びます。
このコンテキストでは、データ構造の特定の部分を常に/ほぼ常に/一般的に操作するには、特定のブックキーピングを行う必要があります。ツリーのルートを更新するとき、ルックアサイドキャッシュを削除する必要がある、または外部データ要素にアクセスするときに、ロックを取得/解放する必要があるとします。これらの場合、DRYプリンシパルを適用し、それらのアクションをまとめてまとめることが理にかなっています。
プライベートコンテキスト内では、ファミリ内の他の関数がこれらの「ゲッターとセッター」を回避し、データ構造を操作することが可能です。したがって、なぜそれらをアクセサおよびマニピュレータと考えるのでしょうか。データに直接アクセスするか、別の家族に頼ってその部分を正しくすることができます。
保護されたゲッター/セッター
保護されたコンテキストでは、パブリックコンテキストとそれほど違いはありません。おそらく不正な外部機能は、データ構造へのアクセスを望んでいます。いいえ、存在する場合は、パブリックゲッター/セッターのように動作します。
this->variable = x + 5
、またはUpdateStatistics
セッターで関数を呼び出すと、そのような場合classinstancea->variable = 5
に問題が発生します。