オブジェクト指向単語

オブジェクトシコウ
  • 6
  • 0pt
掲示板へ

オブジェクト指向とは、プログラムひいてはシステムにおける構成要素を
オブジェクトとして捉える概念である。

プログラミングにおけるオブジェクト指向

オブジェクト指向におけるプログラミングとは特定データ構造と振る舞いを持つものを全て物体(オブジェクト)として捉える概念である。

オブジェクト指向では、システム上における、構成要素を分析し、その特徴をまとめてクラスとして定義する。プログラム実行時にクラスの中身としてのデータ群を具体的に決定し、メモリ上にそのデータ群をまとめて配置した塊をオブジェクトと呼ぶ。
クラスにはそのオブジェクトが、どのような内部状態を持つか、どのような操作でどのように内部状態を変化させるべきかを記述する。クラスの構造がプログラム実行前に静的に決まって変更できない言と、実行時であってもクラスの構造の変更を行える言が存在する。

オブジェクトが作用しあって、その内部状態を互いに変化させながら処理が進行するようなプログラムを作ることがオブジェクト指向プログラミングである。オブジェクト指向言と呼ばれる言を使用したとしても、必ずしもオブジェクト指向プログラミングとなるわけではない。

オブジェクト指向プログラミングにおいて、クラス概念を持つ言プログラミングする場合がほとんどである。しかしクラスというものを排除してオブジェクト指向を実現した言(SelfLENSなど)も存在する。

三大要素

カプセル化

オブジェクト内のデータを隠蔽することにより「振る舞い」のみに意識させるために行う。

継承(インヘリタンス)

オブジェクトの機を引き継ぐことをす。

多態性(ポリモーフィズム)

オブジェクトの詳細な実装が異なっていたたとしても共通した呼び出しで利用することが出来る

もっとわかりやすく言うとどういうこと?

オブジェクト指向はプログラマー初心者にとって、まさに最初の壁になり、脳味噌パーンと弾けた人も少なくないと思われる。

しかし、それは専門的な用であると決めつけて難しく考えるからいけないのだ。もっとわかりやすく言えば、オブジェクト指向というのはクラスという一つの作業があり、それぞれにメソッドといわれる工程を伴っている、ある的を達成するために必要な作業工程をひとまとめに考えたものと捉えればいい。

例として木版画を挙げてみよう。木版画は名の通り、まず版木に下絵を描き、それに合わせ彫刻で彫り、掘った版木に絵の具を付けて摺ることによって完成する作品である。そして、江戸時代には既に絵師、彫師、摺師による分業制が確立していた。これをラオジェクトwwwという呼び名で名高い(?)Rubyでオブジェクト指向で説明するとこうなる(defは関数定義。また、本来関数変数の名称に漢字やかなは使えないのだが、あくまでわかりやすく説明するため)

class 版画
 def 描く
  #絵師の工程
 end

 def 彫る
  #彫師の工程
 end

   def 摺る
      #摺師の工程
  end
end

このように、オブジェクトというのは一つの単位で現す作業とその作業に必要な工程の集まりなのは説明した通りで(ここでは版画を制作するという作業に対し、描く、彫る、摺るという工程が一つのグループになっている。

そして、絵師が描き、描いた作品を彫師が彫る、彫った作品を摺師が摺る、という工程が行われ、最後の摺る作業が終えて、初めて一つの作品が完成することで、的が達成されるわけである。

作品 = "" #ここに作品が作られていく
版画制作 = 版画.new #今から版画を作ります
版画制作.描く
版画制作.彫る
作品 = 版画制作.摺る

インスタンス

また、上の版画制作にあたる変数は、インスタンスという。よく、オブジェクト指向を説明したサイトでは雛形などと説明している。だが、これ自体は実体を伴っているものではなく、どちらかというとクラスという作業における作業マニュアルのようなものである。このインスタンスは基本、与えられた工程以外の作業を命することはない。

また、版画という作業(クラス)に対し、版画制作という作業マニュアルインスタンス)が与えられることによって、その版画の題材が北斎だろうが広重だろうが、どれも同じように、描く、彫る、摺るという作業が行われるようになる。

このように、一度インスタンスを作ってしまえば、後は同じ作業を繰り返し行える特性インヘリタンス(継承)という。また、このインスタンスに用いる変数名は何を定しても良い。わかりやすく作品名としてもいいし、クラス名と同じにしても良い。

オブジェクト指向の利点とカプセル化

では、このオブジェクト指向、何が便利かというと、似たような作業をグループごとにまとめることができるからである。そして、それによって高い品質を保障できることが大きい。たとえば、この工房では版画以外に彫刻、油なども作っている作業場があるとする。ここで彫刻の作業場で何らかのミスを犯したとしても、版画や油の作業場には何もがない。これと同じ理屈で、クラス内で起きたバグは、クラス内だけを見直せば済むからである。この作業工程の隠蔽(他の作業場には版画の作業工程は見えない)のことを、カプセル化という。

なお、似たようなものに配列があるが、配列一つの単位におけるグループの集まり配列学校の学年、インデックスクラス番号と思えばいいだろう)であり、作業工程といった動作を伴ったものではない。

変数とスコープ

変数はオブジェクト指向において、少し解釈が面倒である。一般的な変数は、その関数内でしか使えなかったり、そのページ内でしか使えなかったりするものが多い。だが、オブジェクト指向の場合は、大元のクラスにおいて、クラスグループ内ならばどこでも使える変数、そのクラスだけで使える変数、そして、どこでも使える変数などを定義することができる。この変数が及ぶ範囲をスコープという。

例でいえば、この版画の作業で、全部の工程にかかわっているものは版木であり、これを一つの変数としてみる。すると、この”版木”は作業工程の中で絵師鉛筆で描かれたり、彫刻で掘られたり、絵の具を塗られたり、に摺られたりしているわけであり、この”版木”をわざわざ、描く、彫る、塗る工程ごとに”版木です”と定義するのはナンセンスな話である。したがって、この”版木”という変数スコープは作業全体に定義させた方がいいだろう。

一方、彫刻バレンという具をそれぞれ変数に当てはめてみても、それを使用するのはそれぞれ彫師と摺師だけであるので、これを、版画制作という作業工程全部で定義するのも効率が悪い話である。この場合は、それぞれの彫る、摺るというメソッドだけで定義すれば済む話である。

これをプログラムの話に当てはめてみて、実際のプログラムの中でも変数は、”版木”のようにずっとクラス内で色々代入が行われているほど参照頻度が高いものもあれば、”彫刻”や”バレン”のように、一時的な命や判定なだけに用いられるものもあるわけである。

つまり作業において発生する物や出来事に対して、関係あるものとないものを振り分けることができるのが、変数スコープの役割である。

セッタとゲッタ

では、変数に軽く触れたところで、駄と下駄…もといセッタゲッタについて解説する。セッタ(setter)とは名の通り、共通で用いる変数を外部から取得する的で作られるメソッドであり、ゲッタ(getter)とは名の通り、クラス内で生成された変数を、元のメインプログラムに返すために作られるメソッドである。

つまり、版画の場合でたとえると、版木、また彫刻バランといった作業具類は元々のメソッドには用意されていないため、外部から仕入れる必要がある。そのために、外部から現在の版画クラスメソッド活用するために、セッタを使い、外部から変数を取り入れるわけである。

対して、ゲッタというのは、そのクラス内におけるメソッドによって完成したもの、あるいは次の工程に必要なものを外部に送り出す役割を持っている。ここで返す必要があるのは摺られた木版画の作品そのものがそれに当たる。上記では作品と表したが、実際にはゲッタで送り返すものは版木そのものではなく、完成品としての木版画そのものがそれに当たる。

コンストラクタ

また、オブジェクト指向にはコンストラクタという仕組みを実装しているものも多い。コンストラクタとは名の通り、構築するものという意味であり、最初のインスタンス実装する際に、同時に変数として送り込み、コンストラクタによって、インスタンス定義用のメソッドで自動的に処理される仕組みであり、いわば料理の下拵えのようなものである。

たとえば、上記の例で、版画制作=版画.Newと記述する際に、インスタンス生成時に変数も設定しておく形となる。そうすれば、次のメソッドが実行される前に、インスタンスを生成したタイミングで、コンストラクタが働き、作業用メソッドを実行する前に、事前処理をしてくれるわけである。

実際の木版画の工程でも、版木が用意されればすぐに絵師が絵を描くものではなく、ある程度、洗浄や研磨といった下準備を行ってから描いていく。これをプログラムに置き換えてみると、

版画制作=版画.New(版木)
作品 = 版画制作.描く

と記述できる。コンストラクタに下準備のプログラム実装しておくことによって、絵師の描くというメソッドを実行できるようになる。

継承クラス

次の説明に入る前に、継承クラスの説明をしておこう。

上記の例でいえば、版画における絵師の描く仕事にも構図、描画などの工程がある。また、彫師には彫るなど、摺師には絵の具の調合や摺るなどの作業工程があり、細分化されている。その場合、継承クラスを定義することによって、版画の作業を更に細分化することができる。このうち、版画における絵師の作業を継承クラス化してRubyで表すとこう表現できる。

class 絵師 < 版画
 def 構図
      #構図をとる工程
 end
 
 def 描画
      #描く工程
 end
end

これが継承クラスであり、要は作業工程が更に細かい作業工程へと細分化されているわけである。

ポリモーフィズム(多様性)

さて、カプセル化インヘリタンスはそこまで難しくない。だが、このポリモーフィズムを説明するには、ちょっと木版画だけでは足りないので、この版画作業場では木版画だけでなく、石版画、版画も作るとする。そして、石版画も同様に描く、摺る、彫るという工程があり、担当の絵師は石版画、版画も担当しているとしよう。すると、上述した継承クラスにいる絵師は石版画、版画とも継承クラスの関係にある。このように、同じ名前メソッド複数のクラスで使い回せるような状態のことをポリモーフィズムという。

下の例では、各クラス内に同じ”描く”というメソッドを定義しているが、それぞれクラス名が異なっているので、同じ描く命でも、実際に実行している工程は異なっているわけである。

class 木版画
    def 描く
  end 
end

class 石版画
     def 描く
   end
end

class 版画
    def 描く
  end
end

class 絵師
 def 描く
 end
end

こういうことである。

抽象クラス

オブジェクト指向の大まかな概念がわかってきたところで、頻出する抽クラスインターフェースの説明をしたいと思う。クラスとは名の通り「具体的なことが記されていない工程」にあたり、上の例だと、絵師クラスがそれに当たる。なぜなら、絵師責任者から「描いて」と言われても、木版画の下絵なのか石版画の下絵なのか、版画の下絵なのか、それとも別の業務なのかわからない(つまり、的にしか工程が命されていない)からである(※なお、Rubyには抽クラスの定義はない)

だが、同時に版木が渡されたら「ああ、木版画ですね」とわかるし、石ならそれぞれ石版画、版画とわかるだろう。このように、抽クラスの場合は、必ず、それの抽的な「描いて」という作業に対し、何を「描く」のか判別する判断材料(ゲッタとセッタを置くことが多く、そこで必要な情報をやりとりする)は上位クラスに用意されている。また、インスタンスも直接継承クラスに対して示しないとエラーとなる。なぜなら、木版画という上位クラスに「描いて」という命を出しても、そこにあるのは作業マニュアル材料だけで、絵師は継承クラスにしか存在しないからである。

インターフェース

対してインターフェースというのは逆の視点となる。それこそ版画の作業場では木版画にしても、石版画にしても版画にしても、絵師に作業を頼むことになるからであり、言い換えれば絵師は木版画や石版画、版画…の継承クラスに位置するわけである。

では、クラスという概念との違いについてであるが、クラスは、作業はそれぞれ複雑な工程があるが、それによって作られるもの(出される値)は同一種である。それに対しインターフェースは、作業は同じだが、それによって作られるものは多様に富んでいるということである。つまり、上記の例では木版画、石版画、版画などをひっくるめても、結局は描く、彫る、摺るという同じ作業が行われているからである。

なお、継承クラスは複数の親クラス定できないが、インターフェースの場合は複数の親を持つことができる大きな違いがある。

静的メソッド・静的メンバ

さて、今までは同じ作業の中で工程をグループ化するものと定義してきたが、実際はそうでないケースもある。それが静的メソッドあるいは静的メンバであり、ここではクラスに値するものはただの組みでしかなく、クラス名によってカテゴライズしているだけである。たとえば、アメリカ合衆国カジノが合法化されている州とそうでない州があるが、実際その州のカジノが合法であるかは、実際調べてみる必要がある。だが、逆にそれさえわかってしまえば、ほかは調べる必要がない。それを静的メソッドで表現するとこのようになる(Rubyではその概念はなかったので、Pythonで記述する)

class アメリカ合衆国:
    @staticmethod
    def nevada():
        print("カジノは合法です")
    def tennessee():
        print("カジノは違法です")

アメリカ合衆国.nevada() カジノは合法です
アメリカ合衆国.tenessee() #カジノは違法です

別に作業を工程化しているわけではないので、そのメソッドは他のメソッドとは直接関係を持っていないことがわかる(仮に50州のカジノ情報があったとしても、利用者は全部覗かなくても、必要な州の情報さえわかればいいので)。

つまり、今まではダイナミックな作業という流れがあったのに対し、このメソッドお互いに他のメソッドに全く干渉していない、静的な働きしかしないため、静的メソッドと呼ばれているのである(なお、メソッドはメンバともいうが、メソッドが働きをするニュアンスに対し、メンバとはただカテゴリーに属する存在《メンバー》というニュアンスがある)。

また、予めアメリカ合衆国クラスを定義しようとしてインスタンスを作らなくても、いきなりアメリカ合衆国にあるネバダ州、アメリカにあるテネシー州というに直接メンバを参照すれば、そこでカジノができるかどうか分かるわけであり、むしろ静的メンバにおいてはインスタンスの生成はできない(する必要がないから)。また、仮に別のに同じ名前があったとしても、最初からアメリカネバダ州、とカテゴリーを宣言しているわけだから、多様性も保障されることになる。

【スポンサーリンク】

  • 6
  • 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

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

お絵カキコがありません

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

ピコカキコがありません

オブジェクト指向

43 ななしのよっしん
2018/09/05(水) 00:19:41 ID: pF4vmaDKf+
人間.年齢」変数は「経年」関数を通してしか変化させることができず、「経年」変数では「人間.年齢」は増えるだけで決して減ることはない
そして「経年」変数によって「進学」「卒業」「入学」「就職」「留年」「就職浪人の開始」等が行われる
アクセス制御がかかっているので「人間.年齢」がバグったプログラムで減ったりすることはいことが「人間クラス単独で保できる

大体現場で使うのはこの辺と継承まで
継承も現場で使われるのはソースの共通化的で「〇〇Base」なんて作るくらいしか使われない
化がどうのと言い出すを見たら近寄らない方がいい
44 ななしのよっしん
2019/02/10(日) 18:54:43 ID: QaDxJ3dTMM
継承の方がむしろ割とどうでもよく、「インターフェースに対してプログラムを書く」ことの方が必要だし、それができないやつは現状使い物にならんと思うけどな。もっというと、自分だったらソースの共通化を的としてベースクラス作る人間は疑ってかかるなぁ。悪いけど。
45 ななしのよっしん
2019/03/15(金) 22:21:42 ID: r22ZMJCq5U
>>44の言う通りソースの共通化的で継承を使うのはアンチパターン
単にソースを共通化したいがために継承を使っていくと、リスコフの置換原則に違反する捻れたコードが出来上がっていくだろう。

「『適切な』インターフェースに対してプログラムを書く」ことで、ある変更のインターフェースの向こう側に波及しなくなることはオブジェクト指向の大きなメリットですわな。
46 ななしのよっしん
2019/10/11(金) 11:43:29 ID: glEhW4RBJk
>>32
オブジェクト指向は機分割データ分割ではなく、責務分割するからそのようなメリットが出るんだろうな。
役割が明確になった上で分割されるから、クラスを見たとき、そのクラスはどんな役割を持っているのか分かりやすい。
大勢の開発で楽の根拠はオブジェクト指向による責務分割だと思う。

あと、過去の自分は他人という考え方もできる。
だから個人開発でもオブジェクト指向は使えるのは同意。
オブジェクト指向向は未来の自分も含めた他人にオブジェクトを使わせることに意義があると思う。
47 ななしのよっしん
2019/11/12(火) 00:36:01 ID: QK6qkYoffx
>>42
それはむしろ性的…

じゃなくて静的メソッドだな。ただの紐付け情報
48 ななしのよっしん
2020/01/23(木) 19:47:13 ID: QaDxJ3dTMM
そもそもビャーネ先生カプセル化・継承・多態を三要素と言いだしたのが間違いのもとで、これらは言設計の分析としては正しいが、プログラム書く側にとっては覚えてもあんまり意味ないしむしろ下手に意識すると間違う。結局三つともしてるところは一つで「モジュール間の結合は実装ではなく仕様に対して行うもので、広い意味で『同じ』と見なせるものは同じに扱えるようにしとけ」ということ。
『同じ』とは何なのかといえば、機セットとしてのインターフェースが等しいということで、やってることはOOP以前からある要件定義と何ら変わらない。何ができて欲しいのかという定義が抽化(カプセル化)であり、同一性の補助メカニズムとして継承・多態がつく。OOPやってれば必然的に入っては来るけど、やったらOOPになるって性質ではないし、三つを対等に捉えるのもなんか違う。
だから大事なのは実装仕様は剥がしとけというただこれだけの話であって、普段OSAPI呼ぶような時でもみんなやってるし、その延長で考えてけば別段難しいものではない。
49 ななしのよっしん
2020/01/30(木) 11:59:15 ID: hE7yiyIc6p
よく使う処理をひとまとめにする -> 関数

一緒に使うデータをひとまとめにする -> 構造体

データとそのデータの取り扱い方をひとまとめにする -> クラス

種類の違うデータでも同じ使い方が出来ると便利だよね -> ポリモーフィズム

じゃあポリモーフィズムに必要な「同じ使い方」の仕様書を作ろうぜ -> インターフェース

インターフェース通りに設計することを強制しよう -> 継承

(省略しています。全て読むにはこのリンクをクリック!)
50 ななしのよっしん
2020/02/03(月) 00:32:44 ID: kwm5EpKaBs
変数プログラミングという解釈はどうでしょうか?

ノイマンコンピュータプログラムデータとして扱うから
プログラムを格納できる変数があってもいいよね、みたいな。

そのうえで、ポインタで扱ったほうが融通が利きやすいので、
javaなどでは参照として扱わせるという解釈で。
51 ななしのよっしん
2020/04/07(火) 18:18:27 ID: 1APB64X2nE
以下の動画の説明が分かり易かった。
あくまでも大雑把な理解にはなるけど。

>>sm25744960exit_nicovideo
52 ななしのよっしん
2020/10/03(土) 09:05:52 ID: QK6qkYoffx
PHPerにこそ覚えて欲しい記述法。自分はオブジェクト指向を採用してから、メンテナンスや追加実装の工数が半減以下にまで短縮された

>>46
まさにそれ。過去の自分は他人、そんな一言一句憶えてないしな

急上昇ワード改