オブジェクト指向単語

オブジェクトシコウ
6.9千文字の記事
  • 7
  • 0pt
掲示板へ

オブジェクト指向(object oriented)とは、1980年代以降ずっと流を占めているプログラミングパラダイムである。

概要

オブジェクト指向とは、手続きをオブジェクト(対)を単位として考えることによって、「対を(が)〜する」という人間の思考に近い形でプログラミングしようとするプログラミングパラダイムである。

C言語を代表格とする手続き型言語の欠点を修正するような形で1980年代に普及した。C++はその普及のさきがけであるが元祖ではない。普及以降、関数型プログラミングからは異論があるかもしれないが、2021年現在においても流のプログラミングパラダイムである。

クラス

オブジェクト指向プログラミングで中核をなすの型理論に基づくクラス概念である。オブジェクト指向の三大要素とされるカプセル化・継承・多態性クラスの性質に関するものである。

クラスオブジェクトが保持するデータ構造とそれに対する操作をまとめたもので、共通する性質を持つオブジェクトをひとまとめにする働きがあるのだが、長くなるので詳しく知りたい人向けには後述することにする。

細かいことを言えば、プログラム実行時にクラス構造を変更できない言(クラスベース)と、変更をできる言(プロトタイプベース)が存在するが、プログラミング中級者までは気にしなくてよい。中には、クラスというものを排除してオブジェクト指向を実現した言(SelfLENSなど)も存在するが、プログラミング言語マニアでもない限り忘れてよい

明確な定義はない?

オブジェクト指向は流かつ人気プログラミングパラダイムであり、大抵の実用的プログラミング言語で採用され、各種解説書でも推奨されている。

しかし、実際にはオブジェクト指向はプログラミング言語毎、さらには解説者毎にアレンジを受けており、言解説者によって意味するところは異なっている。つまり、オリジナルとされる定義や上記三大要素のように一定の支持を得ている定義もあるにはあるが、オブジェクト指向に決定的な定義はないとも言える。

だが確固とした定義がないがゆえに、「はっきりわからないけど、従えば万事うまくいくものがオブジェクト指向のはず」
といった逆転的論理によって、オブジェクト指向を格化してしまってはいないだろうか。

大まかな傾向は一致していても詳細な定義が人それぞれである以上、うまく行かない場合があるのは当然のことであり、「オブジェクト指向ならうまくいくはずだから、うまくいかないのは自分がオブジェクト指向を理解できていないせいだ」といった卑屈な思考にとらわれる必要はない。

自分の信じるオブジェクト指向でうまく行かない時に、立ち止まって他の考え方に視野を広げればよいだけの話ではなかろうか。オブジェクト指向は的ではなく、あくまでもうまくプログラミングするための手段なのだから。

関連項目


もっと具体的に知りたい人向け

以下ではプログラミング未経験者でも読めるように、出来るだけ特定プログラミング言語依存しない記述を試みるが、長いので下記を参考に希望レベルまで読み進めること。

  • オブジェクト指向の雰囲気とクラスについて具体的に知りたい → 詳細まで
  • 三大要素とされるカプセル化・継承・多態性の説明も欲しい→ 利点まで
  • オブジェクト指向を越えたい → 難点まで読んだ後、修行して悟りを開くのじゃ

免責事項

詳細

あなた(プログラマー)が動物園の飼育員(コンピューター)の監督に就任したとしよう。あなたは飼育員に対して飼育マニュアル(プログラム)を通じて示することしか出来ず、自ら動物と触れ合うことは出来ない。

説明のための例示であり、実在動物園・飼育員・監督動物等及びその動作とは一切関係ない。異論は認めない

Before

この動物園にはA, B, Cという名前の3頭の虎がいる。

あなたは思考を放棄してすべての手順(手続き)を逐一書き出すことにした。

飼育員の業務

虎Aに対し10kgを用意する。
虎A用の10kgを1kgごとに切り分ける。
虎Aの檻に切り分けたを置いてくる。
虎Aは満になる。
虎Bに対し10kgを用意する。
虎B用の10kgを1kgごとに切り分ける。
虎Bの檻に切り分けたを置いてくる。
虎Bは満になる。
虎Cに対し10kgを用意する。
虎用の10kgを1kgごとに切り分ける。
虎Cの檻に切り分けたを置いてくる。
虎Cは満になる。

上記でもゲシュタルト崩壊して十分読みづらいが、さらに虎の数が増えた時に収拾がつかなくなることは想像に難くない。読みづらいと間違いにも気づきにくくなる。「虎C」と書くところを「虎」としてしまっていることに初見で気づいた人はどれくらいいただろうか。

After

オブジェクト指向を導入すると、上記のマニュアルは以下のようになる。

虎は空腹になったり満になったりする。

餌のやり方

虎に対し10kgを用意する。
虎用の10kgを1kgごとに切り分ける。
虎の檻に切り分けたを置いてくる。
虎は満になる。

飼育員の業務

虎A, B, Cに餌をやる。

なんということでしょう

業務内容をA, B, Cという対(object)を単位として整理するという方針に従えば(oriented)、A, B, Cは「虎」に分類(classify)されてひと括りに扱うことができるようになり、 飼育員のすることは変わっていないのにマニュアルの見通しが良くなったのである。

これなら虎の数が少々増えても読みづらくはならない。また、現実監督が飼育員に示する時もBeforeよりAfterのやり方になるであろうことから、より人間の考え方に近づいているということもおわかりいただけただろうか

用語解説

オブジェクトについて

オブジェクトには「対」以外に「物体」という訳もあるが、スレッドHTTP接続、果ては関数など形のないものまでオブジェクト(対)化できるので、オブジェクト = 物体 という考え方に囚われるとよろしくない。

さらに厳密に言うと、オブジェクトは対の状態を記録したプロパティを束ねたデータ集合体であり対そのものではない。冷静に考えれば虎「A, B, C」は、それぞれにつけられた名前であって虎そのものではないのだから当然なのであるが、これを忘れると後で虎が異次元間に消えたり、何もないところから突然現れたりすることになる。

利点

柔軟性

後になって、虎の餌用のを1kgではなく0.5kgごとに切り分けなければならないことが判明したとしよう。オブジェクト指向導入前であれば虎A, B, Cのそれぞれについて全3ヶ所の変更が必要であったが、オブジェクト指向導入後であれば「餌のやり方」の項を1ヶ所変更するだけで済む。

虎Dが増えたとしても、オブジェクト指向なら「虎A, B, C」を「虎A, B, C, D」とするだけである。

このようにオブジェクト指向が導入されれば状況の変更にも柔軟に対応できるようになるのである。

部品化

例えば上記の「虎」の章の部分の執筆を部下に任せることができる(部下がいるほど偉ければだが)

一旦任せてしまえば、たとえば先述のの切り分け単位が変わったケースでもあなた自身が対応をする必要はない。

また、任された部下が、虎のプロパティ空腹か満かを記録する代わりに、その日に食べたの量を記録して、10kgに満たなければ空腹であると判断するようにしても、あなた自身はそれを気にする必要はない。

このように、内部実装を外部から見えないようにする(見なくて良いようにする)ことを、クラスカプセルに見立ててカプセル化とか実装の隠蔽などと呼ぶ。

カプセル化により、あなた自身は「虎」の細かいことは気にせずに「飼育員の業務」の章の執筆に専念することができる。また、「虎」の章だけを部品のように「動物園」から持ち出して、「サーカス」や「アフリカ動物保護施設」のような別の施設で使ってマニュアル執筆の手間を大幅に省くこともではない。

共通化

虎DではなくサイE, Fが増えたとしよう。以下のような対応が可である。

動物

動物空腹になったり満になったりする。

餌のやり方

動物に対し餌を用意する。
動物の檻に用意した餌を置いてくる。
動物は満になる。

虎は動物である。

餌の用意

虎に対し10kgを用意する。
虎用の10kgを1kgごとに切り分ける。

サイ

サイ動物である。

餌の用意

サイに対しを10kg用意する。(切り分けなくて良い)

飼育員の業務

A, B, Cは虎である。
E, Fはサイである。

動物A, B, C, E, Fに餌をやる。

「虎」と「サイ」の共通点である「動物」という性質(分類)を記述することにより、虎とサイについては相違点である餌の用意方法だけを記述すれば済むようになっている。そして、餌をやる時も「虎」と「サイ」について別々に記述せず「動物」とひと括りにして餌をやることができるのだ。

「虎」と「サイ」よりも「動物」の方が抽的なので、抽化と呼ぶこともある。実際のプログラミングでは「動物」のような分類ではなく、「餌を食べるもの」「歩くもの」のような抽化を行うことも多い。

用語解説2

リスコフの置換原則

サブクラスインスタンスは必ずスーパークラスの性質を備えているべきであり、スーパークラスインスタンスと置き換えて使用することができるという「継承」の原則論。

上記でいうなら「動物X」と書かれているところがあれば、「虎A」や「サイF」で置き換えてもマニュアルとして意味不明や実施不可能にならないということ。

これを満たさない継承はおそらくまともに動作しないのでやってはならない。

難点

プログラミングミスの話をしよう。

プログラミングコーディングよりもデバッグの方が大変だという話もあるくらいで、ミスによるバグをなくすというのもプログラミング言語やパラダイムの大事な役割である。オブジェクト指向により手続き型プログラミングと呼ばれる旧来のスタイルよりもバグは大幅に減ったが、それでも問題点を全になくすことはできなかった。概要で述べたようにオブジェクト指向は全てを解決する銀の弾丸ではない。

以下ではオブジェクト指向が批判される原因となるミスについて、上記の例を引き継いで解説しようと思う。単純化して説明するので「そんなミスするいねーよ、バーカ」とか思ってしまうかもしれない。しかし、日々繰り返したり、他のことと組み合わさって複雑になったりすると実際に起きてしまうのだ。

状態変化

以下のルールを追加する。

虎は、満時に餌を与えると過食により死亡する。

なお、虎が死亡するとあなたは監督責任を問われてクビになる(プログラム異常終了)。


動物園は発展し、あなたは出世して部下に各動物マニュアル作成を任せ、自身は「飼育員の業務」の章の執筆に専念できるようになった。そんな折、「猛ショーをやるぞ」という園長の掛けのもと手順書が以下のように変更された。単純化のためサイは来なかったものとする。

飼育員の業務

虎Cを猛ショーに出演させる。
虎A, B, Cに餌をやる。

ところが、猛ショー開演当日の閉園後、虎Cが死亡したという報告が届き、あなたはクビになった。

どうしてこうなった

実は部下に任せていた「虎」の章は以下のようになっていたのだ。

虎は空腹になったり満になったりする。
虎は、満時に餌を与えると過食により死亡する。

餌のやり方

虎に対し10kgを用意する。
虎用の10kgを1kgごとに切り分ける。
虎の檻に切り分けたを置いてくる。
虎は満になる。

猛獣ショー

虎が芸をするごとに褒美としてを1kg与える。
虎が満になったら終了。

虎Cは猛ショーでご褒美をもらって満になっており、この状態で虎A, Bと共に餌を与えられたため過食により死亡したのだ。

このような不幸事故が起こった原因としては色々考えられるが、一つはマニュアルにおいて虎Cと書かれているだけでは虎Cが空腹なのか満なのかわからないということが挙げられる。つまり虎Cというオブジェクト空腹という状態と満という状態両方が存在しうることが問題なのである。

またカプセル化により「猛ショー」のメソッドの中身を意識しなくなったことも原因の一つといえるかもしれない。

この問題を回避する方法は一通りではないのと、方法(参照透過)によっては空腹な虎が異次元間に消えたりするのでここではこれ以上深入りしない。

オブジェクト指向ではオブジェクトの状態が変化していくことが前提なので、参照透過とは相性が悪いとされている。

不適切な共通化

化・共通化は利点であるが、共通化した部分に個別に変更する部分が生じた場合、また非共通化することになる。


サイが登場した例に戻って説明する:

虎はなので逃走のリスクを下げるため、虎の檻だけを二重にしたくなったとする。檻の出入りは「動物」のメソッドで共通化しているので、虎の檻の出入りの手順だけを変更しようとすると、せっかく共通化した「檻の出入り」の部分を「虎」と「サイ」で別々に書き直さなければならない。別々に書いてあれば「虎」の変更だけで済んだのに、「動物」「虎」「サイ」の3ヶ所に変更が生じてしまう。


継承によるプログラムの部品化はオブジェクト指向の特色とされている。確かに、各プログラミング言語の標準ライブラリレベルで十分な時間と人手をかけて検討されテストされた継承であれば、オブジェクト指向の利益を最大限に享受できるだろう。しかし、末端プログラマーがその場の思いつきで共通部品化したものについては継承により予期せぬ不具合を引き起こすと言われており、言仕様上は継承をサポートしていても積極的に継承を利用することは勧めていない場合もある。

おまけ: 宣言型プログラミング

状態変化による悲劇を避ける方法の一つに、状態変化を禁止してイミュータブルとし関数型言語による宣言型プログラミングを行うという方法がある。

宣言型プログラミング

【スポンサーリンク】

  • 7
  • 0pt
スマホ版URL:
https://dic.nicovideo.jp/t/a/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91

この記事の掲示板に最近描かれたお絵カキコ

お絵カキコがありません

この記事の掲示板に最近投稿されたピコカキコ

ピコカキコがありません

オブジェクト指向

67 ななしのよっしん
2021/04/06(火) 21:29:55 ID: ijrbyBe0Ys
まー焦る理由がどこにあるわけでもないしね
納得行く仕上がりになるのをのんびり待ってるよ
68 ななしのよっしん
2021/04/06(火) 21:33:45 ID: WENFPn7Exi
新卒SEワイ、楽しみ
69 ななしのよっしん
2021/04/19(月) 22:55:32 ID: alUXU8m+kl
SE(システムエンジニア)ならほとんどオブジェクト指向は使わないんじゃないかな……
70 ななしのよっしん
2021/04/24(土) 00:35:24 ID: QK6qkYoffx
>>66
つまり、前に書いた人の記事は全くクソの役にも立たなかったゴミ記事だったと言いたいわけですね。跡形も何もなく消し去ってくれてありがとうございます

他の記事でもそういう今まで書いてきた人の苦労を簡単に踏みにじるような血の入れ替えを是非続けてください

自分はもう記事を書くのやめましたから好きにどうぞ
71 ななしのよっしん
2021/04/24(土) 08:20:24 ID: inzcQWhwBB
>>70
nrpoon氏でしたか。>>65を含め過去レス一通チェックしていたのですが全然気づきませんでした。

> 全くクソの役にも立たなかったゴミ記事だったと言いたいわけですね。
そこまでは言いません。ただ、>>56摘したような混同部分を分離しようとすると、自分の技量では1から書き直さないと難しかったです。

元の記述を消したことについては>>60の時に予告してから今回の実施までに十二分に反論の機会を提供いたしました。今頃になって>>70ような言動に及ばれるというのは極めて遺憾です。

他にも言いたいことはありますが、差し戻しの要はないとのことなのでここまでにいたします。
72 ななしのよっしん
2021/04/24(土) 17:29:34 ID: ijrbyBe0Ys
例え過去に書いた経緯があっても、書く気がないと宣言した人間はただのROMなので気にしないでいい
それより満足いくものに仕上がったかい?仕掛かり中にコメントするのもなんなので黙って見てたけども
73 ななしのよっしん
2021/04/24(土) 19:22:09 ID: inzcQWhwBB
>>72
途中の編集コメントでも書きましたが、大体書きたかったことは書きました。
もう少し短く書きたかったという意味では満足していませんが。
74 ななしのよっしん
2021/04/24(土) 20:17:16 ID: ijrbyBe0Ys
そいつは良かった
できればもう一すっきりまとめたかった気持ちはにも伝わってくるけど、まあプログラミングの分からん人は利点辺りまでで飽きて寝ても構わんのだろう?という話だし十分良いと思うよ
この辺まで初心者向け、ここからはプログラマの皆様へ、みたいな線引くといろんな人が受け入れやすかったりするかもしれない
75 ななしのよっしん
2021/08/03(火) 00:29:29 ID: glEhW4RBJk
オブジェクト指向コードの具体例

class Taiyaki
属性
生地の種類
具材
操作
価格取得
味の取得
他、ビルダー等を定義

Taiyaki croissantTaiyaki = Taiyaki.Builder
(省略しています。全て読むにはこのリンクをクリック!)
76 ななしのよっしん
2021/08/03(火) 00:31:03 ID: glEhW4RBJk
ドメインモデル貧血症の例

class Taiyaki
属性
-生地の種類
-具材
操作
+生地の種類のセッターゲッター
+具材のセッターゲッター

Taiyaki taiyaki = new Taiyaki();
taiyaki.setDough("クロワッサン生地");
(省略しています。全て読むにはこのリンクをクリック!)