オブジェクト指向プログラミングとは
オブジェクト指向パラダイムにおけるプログラミング.
OOPの性質
🔖オブジェクト指向言語
現在オブジェクト指向言語と呼ばれているものは実際には,
- Abstruct Data Type (Java Integer 型)
- オブジェクト (Java Object 型)
の 2 つを合わせもっている. その意味で, オブジェクト指向言語と言うよりは抽象データ言語というほうが正しい(厳密なOOPというよりはマルチパラダイム).
🐥OOP Basics
📝クラス(OOP)
OOPにおける抽象データ型(ADT)からなるデータ構造.
メソッドと属性を定義する特別なシンタックスを クラス(Class) という. 値と操作をひとつのまとまりとしたもの. 以下の構成要素をもつ.
- 値: Explicite State(明示的状態 .. 時間とともに変化する値).
- 操作: Procedural Data Abstruction(手続的データ抽象).
Class という概念によって, オブジェクトの”宣言”と”生成 (new)“を分離する.
クラスは, 継承・ポリモーフィズム・カプセル化などの, オブジェクト指向プログラミングにおける重要な概念を実現する強力な手段.
📝オブジェクト(Object)
OOPにおける📝データ抽象(Data Abstruction)の実体.
この実体という概念が少しわかりにくいが, 噛み砕くとこれは具体的には, メモリ上のデータをいい, 識別子によってアクセスできる. こういうアクセスできるデータを分類してグループ化しているもの.
📝インスタンス(Instance)
📝クラス(Class)から生成した📝オブジェクト(Object)をインスタンスという.
オブジェクトは一つのメソッドで, 異なる属性をもつ複数のオブジェクトを生成できる. この能力をInstantiation (インスタンス化) という.
メソッドと属性(Methods/Attributes)
オブジェクトは内部と外部はインタフェースを通じてやりとりされる.
内部の明示的状態を Attributes (属性), インタフェースを Methods (メソッド) という.
たとえば, A1 を属性, M1 をメソッドという.
declare
local
A1={NewCell 0}
in
proc {M1 Hoge} end
end
これはクラスでもインスタンスでもないことに注意!!
📝メソッド(methods)
あるクラスないしオブジェクトに所属するサブルーチン. 📝関数.
各オブジェクトが持っている自身に対する操作. オブジェクトは「データ」と「手続き」から成っているが, その「手続き」の部分に当たる.
📝メソッドチェーン
単一の文で同一オブジェクトの複数のメソッド呼出しを可能にする便利な仕組み.
オブジェクトにたいしてドット記法でつないでいくことがおおい.
📝属性(Attributes)
オブジェクト内部の明示的状態を Attributes という.
📝Procedure Dispatch
オブジェクトは単一なエントリポイントをもつ. (エントリポイント = 呼び出し口) エントリポイントに渡される引数をメッセージという. 下の例だと, Counter がエントリポイント. エントリポイントに inc,get メッセージを送る.
{Counter inc}
{Counter get (X)}
エントリポイントから, メッセージに対応するプロシージャが呼びだされる.
メッセージとプロシージャはあらかじめ Dispatch (バンドリング) されている.
OOP Concepts
🔖カプセル化(Encapsulation)
プログラムと内部と内部をインタフェースで分けること. カプセル化のメリットは大規模開発をシンプルにする.
- 正しさを保証する.
- 複雑さを解消する.
カプセル化とはあらゆるものを隠蔽すること
カプセル化がデータ隠蔽というのは狭義の定義.
カプセル化とはあらゆるものを隠蔽すること.
- データ
- メソッド
- 実装
- 派生クラス
- 設計の詳細
- 実体化の規則
- 型
流動的要素を探し出してカプセル化する
ポリモーフィズム
各要素 (定数, 変数, 式, オブジェクト, 関数, メソッドなど) についてそれらが複数の型に属することを許すという性質. ポリモーフィズムはオブジェクト指向固有の概念ではない.
詳細はこっち: 📝ポリモーフィズム
📝継承(Inheritance)
継承. あるオブジェクトが他のオブジェクトの特性を引き継ぐこと.
継承は単に特殊化と再利用を実現する手段ではない. オブジェクトを分類するための手段である.
どう分類するか? 2つの切り口がある.
- 共通性: 時がたっても変わらないものを抽象クラスに
- 可変性: 流動的要素を具象クラスに.
クラスの集合がもつすべての責務を真っ当するためにインタフェースを用意する.
機能追加と機能実装の違い
- 「機能追加」 (スーパークラスが持っていない機能をサブクラスで追加) を目的としたもの
- 「機能実装」 (スーパークラスで定義したインタフェースをサブクラスで実装) を目的としたもの
ref: :Bridge パターン - デザインパターン入門 - IT 専科
📝多重継承
複数のクラスから継承すること. 親クラスに同一のメソッドがあってそれを継承する時, 子クラスはどうするという問題がある. しばしばOOPの議論になる論点.
📝オーバーライド(override)
オブジェクト指向プログラミングにおいてオーバーライド (override) とは, スーパークラスで定義されたメソッドをサブクラスで定義しなおし, 動作を上書きすること.
ref. オーバーライド - Wikipedia
⚖オーバーライド vs オーバーロード
オーバーライド: override vs Overload: オーバーロード
両者はタイヘン混同しやすい. とくにJavaで同じようなポリモーフィズムの実現方法として登場するので.
オーバーライドは継承に紐づく概念であり, さらにいえばオブジェクト指向に関わる. オーバーライドは アドホック多相のオブジェクト指向における実現方法の呼び名.
Related
📝委譲(Delegation)
委譲(Delegation). あるオブジェクトの操作を一部他のオブジェクトに代替させる手法.
- 委譲を行うオブジェクトは委譲先オブジェクトへの参照を持つ
- 必要に応じてその参照を切り替える事で動作にバリエーションを持たせる事ができる.
- プラグイン機構
ref: 委譲 - Wikipedia
コンポジション | Composition
新たなクラスに, 既存クラスのインスタンスを保持する.
has-a の関係 (not is-a)
Prefer Composition over inheritance (Effective Java).
コンポジションと移譲の比較
委譲の実現には多くの場合コンポジションを使用する. 委譲は「目的」であり, コンポジションはその「手段」.
ref: コンポジションとデリゲーション - とある技術メモブログ
関連する Design Pattern
- Adapter
- Proxy
- Facade
- State
- Strategy
- Decorator
📝Mixin
他のクラスから使用されるメソッド群を持つクラスが、他のクラスのスーパークラスにならないで済むための、特別な多重継承関係を実現するためのメカニズム.
ref. Mixin - Wikipedia
Related
OOP Topics
📝シリアル化(直列化/Serialized)
シリアライズ(Serialized). 対義語はデシリアライズ(Deserialized). ネットワーク通信などのために, あるオブジェクトをバイト列や文字列に変換すること.
並列プログラミングにおける🔖逐次化もシリアライズと呼ばれるので注意.
📐継承より委譲
可能な限り、抽象クラスの継承は避ける。インターフェース・委譲を積極的に使おう。どうしても継承を使うなら、慎重に設計しよう。
なぜならば、継承の場合は親クラスの修正で子クラスの修正も必要になるから.
OOPの有名なスローガン.
- 継承より委譲
- 継承よりインタフェース
- Abstractクラスよりもインタフェース
- 🎨Decorator Pattern
- 集約ではなくてコンポジション
- 継承ではなくてコンポジション
委譲よりも継承の場合
is-a関係が綺麗に定義できる場合.
⚖継承と委譲の比較
メリット
- Java の場合継承は一クラスしかできないが, 委譲なら複数可能.
- 継承なら親クラスのメソッドが全て公開されてしまうが委譲なら必要なものだけ公開できる.
デメリット
- 継承に比べてコードの記述量が多くなる.
- 継承は何も書かなければ親クラスの機能が使える.
- 委譲はメソッドの呼び出しを実装しなくてはならない.
ref: オブジェクト指向で. 継承の他に, 委譲といのが出てきますが. これは具
抽象クラスよりもインタフェースを選ぶ(Effective Java)
ref: Effective Java (p93). 抽象クラスよりもインタフェースを選ぶ
実装の観点では,
- 抽象クラスはメソッドに対する実装を含むことを許されている.
- インタフェースはメソッドに対する実装を含むことを許されていない.
機能の観点では,
- 抽象クラスはある機能の実装を強制する.
- インタフェースは任意の機能を混ぜ合わせる.
階層化の観点では,
- 抽象クラスは物事を階層化することに優れる.
- インタフェースは階層を持たないものをまとめることに優れる.
インタフェースは, 階層を持たない型システムを構築する.
- インタフェースは型を定義するために利用する
- インタフェースは定数を提供するために使用しない
- Enum を検討する
- Util クラスを検討する
- 関連するクラスのメンバを検討する
⚖手続き型とオブジェクト指向の違い
ref: 📝手続き型プログラミング
機能分解
ある問題を小さな機能にブレークダウンすることで, その問題を構成する機能要素の洗い出しをすることを機能分解と呼ぶ.
構造化プログラミング的アプローチ
(手続き的な) 機能を適切な順序で呼び出す「メイン」プログラムが必要になる.
メインプログラムにはすべてを正しく動作させる, すなわち機能の組み合わせと呼び出し順序を制御するあまりに大きな責任が課せられる.
結果的にソースコードは複雑になる.
オブジェクト指向的アプローチ
部分機能に対してそれ自体の振舞いに関する責任を持たせ, 実行指示を行うだけであと任せておく. これが委譲 (delegation) という考え方.
🔦クラスとは属性の集合とメソッドの集合のペアデータ構造
クラスとは, Pair (attrs[属性の集合] : methods[メソッドの集合]))というデータ構造.
属性とメソッドはレコードデータ構造によって管理されているだけである!
Lisprならば, ‘((attr1 attr2) (method1 method2)).
Java ならば, こうかいてもいい.
HashMap<String, HashSet<String>> attrs = new HashMap<String, HashSet<String>>();
HashMap<String, HashSet<String>> methods = new HashMap<String, HashSet<String>>();
attrs.put ("Hoge", new HashSet (Arrays.asList ("attr1", "attr2")));
methods.put ("Hoge", new HashSet (Arrays.asList ("method1", "method2")));
References
ものすごくよい記事.歴史が端的にまとまっている.
-
新人プログラマに知っておいてもらいたい人類がオブジェクト指向を手に入れるまでの軌跡 - Qiita
むだに Hoge インタフェースと HogeImpl クラスがあったり, むだに new するだけの create メソッドがあったり, どこで値が設定されてるかわからないオブジェクトがひきまわされてたり, ソースコードを追いにくくするためにやってるとしか思えない, オブジェクト指向なコードをよく目にする.
クラスは単にユーザー定義型であり, 継承は部分型と差分プログラミングを実現する仕組みだととらえるのがいい. オブジェクトがメッセージを送りあうとかメルヘンの世界には入らず, 機能だけ考えるのがいい.
Books
- オブジェクト指向入門
Insights
Related
- up: 📂プログラミングパラダイム
- refs: