基本情報技術者 2018年 秋期 午前(科目A) 問49
問題文
オブジェクト指向における“委譲”に関する説明として、適切なものはどれか。
選択肢
ア:あるオブジェクトに対して操作を適用したとき、関連するオブジェクトに対してもその操作が自動的に適用される仕組み
イ:あるオブジェクトに対する操作を、その内部で他のオブジェクトに依頼する仕組み(正解)
ウ:下位のクラスが上位のクラスの属性や操作を引き継ぐ仕組み
エ:複数のオブジェクトを部分として用いて、新たな一つのオブジェクトを生成する仕組み
委譲(デリゲーション)に関する問題【午前2 解説】
要点まとめ
- 結論→委譲は、あるオブジェクトが受けた操作を自分で実行せず内部の別オブジェクトに依頼して処理させる設計手法であり責務の移譲を指します。
- 根拠→「依頼する」「内部の他オブジェクトに処理を任せる」という記述が委譲の定義と合致するため、選択肢の文言と一致します。
- 差がつくポイント→継承は「振る舞いを引き継ぐ」仕組み、委譲は「実行を他に任せる」仕組みであり、結合度と拡張性の扱いが異なる点を押さえてください。
正解の理由
正解は イ です。
委譲(デリゲーション)とは「あるオブジェクトに対する操作を、その内部で他のオブジェクトに依頼する仕組み」を指します。オブジェクトAがメソッドを受けた際に、自身で処理せず内部に保持する協力オブジェクトBに処理を転送(委任)するのが典型的な形です。選択肢イはこの定義を直接的に表現しているため正解です。
委譲(デリゲーション)とは「あるオブジェクトに対する操作を、その内部で他のオブジェクトに依頼する仕組み」を指します。オブジェクトAがメソッドを受けた際に、自身で処理せず内部に保持する協力オブジェクトBに処理を転送(委任)するのが典型的な形です。選択肢イはこの定義を直接的に表現しているため正解です。
よくある誤解
- 「委譲=継承」と混同する誤解:継承はクラス間で属性や操作を引き継ぐことであり、委譲は実行を他オブジェクトへ任せる別の設計概念です。
- 「委譲は常に複数オブジェクトを合成して新しいオブジェクトを作ること」と考える誤り:委譲は合成(コンポジション)を使うことが多いが、必ず新しいオブジェクトを生成するわけではありません。
解法ステップ
- 問題文のキーワードを確認:「委譲」「依頼」「内部で他のオブジェクトに〜」などの語句に注目。
- 各選択肢のキーワード対比:継承=「引き継ぐ」、合成=「部分として用いる」、委譲=「依頼する」。
- 定義に最も一致する選択肢を選ぶ:今回は「操作を内部の別オブジェクトに依頼する」という文言が完全一致。
- 余力があれば他選択肢の語句(自動適用、生成する仕組み)を検討し誤りを確認する。
選択肢別の誤答解説
- ア: あるオブジェクトに対して操作を適用したとき、関連するオブジェクトに対してもその操作が自動的に適用される仕組み
→ 誤り。これは「自動伝播」や「カスケード」的な振る舞いの説明であり、委譲の定義とは異なります。委譲は「依頼して処理させる」ことが本質です。 - イ: あるオブジェクトに対する操作を、その内部で他のオブジェクトに依頼する仕組み
→ 正解(イ)。委譲の定義と一致します。 - ウ: 下位のクラスが上位のクラスの属性や操作を引き継ぐ仕組み
→ 誤り。これは「継承(インヘリタンス)」の説明であり、委譲とは別概念です。継承はクラス階層で振る舞いを継承します。 - エ: 複数のオブジェクトを部分として用いて、新たな一つのオブジェクトを生成する仕組み
→ 誤り。これは「合成(コンポジション)/集約」や「Compositeパターン」に近い説明であり、委譲とは目的が異なります(ただし委譲実装にコンポジションを用いることは多い)。
補足コラム
委譲は設計の原則「継承より合成を優先せよ(Favor composition over inheritance)」に関わる重要な考え方です。継承は静的な階層による振る舞い共有を行いますが、委譲はオブジェクト間で処理の責務を動的に振り分けることで結合度を下げ柔軟性を上げます。言語例としては、SmalltalkやRubyでの委譲的な設計、Javaではフィールドに別オブジェクトを持ちメソッドをフォワードする実装が典型です。
簡単なPythonでの委譲例:
class Printer:
def print_message(self, msg):
print("Printer:", msg)
class Manager:
def __init__(self, printer):
self.printer = printer # 委譲先オブジェクト(コンポジション)
def print_message(self, msg):
# 自分で処理せず、内部オブジェクトに依頼(委譲)する
self.printer.print_message(msg)
p = Printer()
m = Manager(p)
m.print_message("Hello") # ManagerがPrinterに処理を委譲する
FAQ
Q1. 委譲と合成(コンポジション)は同じですか?
A1. 同じではありません。合成は「他オブジェクトを部品として持つ構造」を指し、委譲は「その部品に処理を依頼する振る舞い」を指します。実装で合成を用いて委譲を実現することが多いです。
A1. 同じではありません。合成は「他オブジェクトを部品として持つ構造」を指し、委譲は「その部品に処理を依頼する振る舞い」を指します。実装で合成を用いて委譲を実現することが多いです。
Q2. 委譲は継承より優れているのですか?
A2. ケースによります。継承はコード共有に便利ですが階層に強く結び付き設計の硬直化を招くことがあります。委譲(合成)は柔軟で結合度が低く、拡張時の安全性が高い場合が多いです。
A2. ケースによります。継承はコード共有に便利ですが階層に強く結び付き設計の硬直化を招くことがあります。委譲(合成)は柔軟で結合度が低く、拡張時の安全性が高い場合が多いです。
Q3. ProxyパターンやAdapterパターンは委譲と関係ありますか?
A3. はい。これらのデザインパターンは内部で別オブジェクトに処理を渡す(委譲する)ことで機能を実現します。目的や追加振る舞いが異なる点に注意してください。
A3. はい。これらのデザインパターンは内部で別オブジェクトに処理を渡す(委譲する)ことで機能を実現します。目的や追加振る舞いが異なる点に注意してください。
Q4. 試験での見分け方は?
A4. 「依頼・委任・内部の別オブジェクトに処理させる」という語句があれば委譲、「引き継ぐ・サブクラス」という語句があれば継承、「部分として用いて新オブジェクトを生成」は合成/Composite系と読み分けてください。
A4. 「依頼・委任・内部の別オブジェクトに処理させる」という語句があれば委譲、「引き継ぐ・サブクラス」という語句があれば継承、「部分として用いて新オブジェクトを生成」は合成/Composite系と読み分けてください。
関連キーワード: オブジェクト指向、委譲、デリゲーション、継承、コンポジション、合成、デザインパターン、Proxy、Adapter、Decorator

\ せっかくなら /
基本情報技術者を
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

