オブジェクト指向の4大原則:カプセル化・継承・ポリモーフィズム・抽象化の実戦理解
動物の種類を増やすたびに、鳴き声を選ぶif文を増やす必要はあるでしょうか?
共通の操作を用意すれば、種類ごとの処理を各オブジェクトへ任せられます。データを守るカプセル化と、共通の約束を守る多態性を具体例で学びます。
なぜオブジェクト指向なのか?構造化設計からの進化
データの内部表現を多数の処理が直接参照すると、変更の影響が広がります。これは手続き型に限った問題ではありません。公開する操作と内部の実装を分けることで、影響範囲を抑えられます。
オブジェクト指向では、「関連するデータ(属性)とそれを操作する手続き(メソッド)を1つのオブジェクト(カプセル)にまとめる」ことで、外部からの不要な干渉を遮断し、部品としての自立性を高めることに成功しました。
オブジェクト指向の4大原則完全整理
オブジェクト指向を成立させる4つの柱の定義と、開発にもたらす具体的メリットを整理します。
原則 | 英語名 | 定義・メカニズム | もたらす具体的効果 |
|---|---|---|---|
カプセル化 (情報隠蔽) | Encapsulation | データと操作をまとめ、許可した操作から利用させる。単にgetter/setterを置くだけでなく、不変条件を守る。 | 公開する操作の契約を維持すれば、内部の変更の影響を抑えられる。 |
継承 (汎化と特化) | Inheritance | 既存のクラス(親/基底クラス)の属性とメソッドを受け継ぎ、新たな差分機能を追加して新しいクラス(子/派生クラス)を作る。 | コードの重複を排除し再利用性を向上。「is-a関係(○○は△△の一種である)」のときのみ適用するのが鉄則。 |
多態性 (多様性) | Polymorphism | 同一のメソッド呼び出し(メッセージ)に対して、呼び出されたオブジェクトの実際の型に応じて異なる振る舞いを動的に実行する。 | 種類ごとの分岐を各実装に移し、共通操作を呼ぶ側の変更を減らす。 |
抽象化 (仕様と実装の分離) | Abstraction | 共通の振る舞いや操作の「インターフェース(枠組み)」だけを抽出し、具体的な処理内容は子クラスの実装に委ねる。 | 「何をするか(What)」と「どうやるか(How)」を分離し、モジュール間の結合度を大幅に下げる。 |
多態性:種類ごとの処理を任せる
多態性では、共通の操作を呼び出す側が、種類ごとの分岐を持たずに済みます。共通の契約を守る実装を追加する場合に有効です。生成・登録の処理や仕様の変更まで不要になるわけではありません。
class Dog:
def make_sound(self):
return "ワン"
class Cat:
def make_sound(self):
return "ニャー"
def make_noise(animal):
return animal.make_sound()
# 呼出し側は共通の操作を使う
print(make_noise(Dog())) # ワン
print(make_noise(Cat())) # ニャーUMLクラス図の基本記法と関係性のルール
クラス間の構造的関係を表現するUML(Unified Modeling Language)クラス図の頻出記号をマスターしましょう。
関係の種類 | 矢印・記号の形状 | 意味と英語表現 | 具体例 |
|---|---|---|---|
汎化 (Generalization) | 白抜きの三角矢印(──▷) | 「is-a関係」(継承関係)。親クラスへ向けて矢印を引く。 | 犬(Dog)──▷ 動物(Animal) |
関連 (Association) | 実線(──) | クラス同士が参照・利用し合う構造的結びつき。 | 社員 ── 部署 |
集約 (Aggregation) | 白抜きの菱形(◇──) | 「全体と部分(has-a関係)」。部分が全体から独立して生存可能。 | パソコン ◇── モニタ(モニタ単体でも存在可) |
コンポジション (Composition) | 黒塗りの菱形(◆──) | 強い結びつきの全体と部分。全体が消滅すれば部分も道連れで消滅。 | 注文 ◆── 注文明細(注文が消えれば明細も消える) |
実現 (Realization) | 白抜きの三角が付いた破線(---▷) | インターフェースで定義された抽象操作をクラスが具現化する。 | リスト実装 ---▷ コレクションIF |
実戦演習問題とステップ別解説
問1:ポリモーフィズムの定義と利点
オブジェクト指向プログラミングにおける「ポリモーフィズム(多態性)」の説明として、最も適切なものはどれか。
クラス内部のデータ構造やメソッドの詳細を外部から隠蔽し、限定された操作のみを公開すること。
同一のメッセージやメソッド呼び出しに対して、受信するオブジェクトの型に応じて異なる振る舞いを実行すること。
既存のクラスが持つデータ構造と手続きを引き継ぎ、新しいクラスを効率的に定義すること。
オブジェクト間の相互作用を排除し、すべての処理を単一のグローバル関数で実行すること。
【正解】イ
【解説】各選択肢の用語対応は以下の通りです。・ア:カプセル化(情報隠蔽)の説明です。・イ:ポリモーフィズム(多態性)の正確な定義です。正解は イ です。・ウ:継承(インヘリタンス)の説明です。
・エ:オブジェクト指向の思想に反する手続き型設計の説明です。
問2:is-a関係と継承の適用判断
オブジェクト指向設計において、クラスAとクラスBの関係が「クラスBはクラスAを継承して定義すべき」と判断できる関係性はどれか。
自動車(A)と エンジン(B)の関係
学校(A)と 生徒(B)の関係
図形(A)と 円(B)の関係
パソコン(A)と キーボード(B)の関係
【正解】ウ
ウが適切です。円は図形の一種なので、図形の操作の契約を守る形で継承を考えられます。自動車とエンジンは全体と部品、学校と生徒は関連です。日本語で「一種」と言えるだけで、実装上の継承が常に適切になるわけではありません。
カプセル化は、値を隠すだけではない
在庫数をprivateにしても、自由に負数を設定するsetterがあれば「在庫は0以上」という条件を守れません。reserve(数量)のような操作で数量と残数を検証し、整合性を保ちます。
手続き型でも、モジュール化や情報隠蔽によって変更に強い設計はできます。オブジェクト指向を採用しただけで品質が保証されるわけではありません。
継承とUMLの記号を読むときの確認点
白抜き三角は親やインターフェースへ向けます。集約・コンポジションの菱形は全体側に置きます。has-a関係は、単純な関連で表せる場合もあります。
コンポジションでは、部分は同時に複数の全体に所属せず、全体の削除に伴って所属する部分も削除されるという強い所有関係を表します。集約の細かな意味はモデルの文脈も確認します。
抽象化は、共通の重要な性質を取り出して詳細を隠すことです。子クラスへの実装委譲だけに限定されません。
出典と仕様を確認する
IPA:FEシラバス Ver.9.2
Python公式:クラス・継承
OMG:UML 2.5.1
次におすすめの学習
編集・検証について
編集・検証:IT資格ラボ編集部
IPAが公開する試験要綱・シラバス・過去問題と、各技術の公式資料を優先して内容を確認しています。制度変更や誤りを確認した場合は、記事を見直して更新します。
編集方針・情報源・訂正方針を見る