オブジェクト指向

出典: フリー教科書『ウィキブックス(Wikibooks)』
移動先: 案内検索
このページ「オブジェクト指向」は、書きかけです。加筆・訂正など、協力いただける皆様の編集を心からお待ちしております。また、ご意見などがありましたら、お気軽にノートへどうぞ。

メインページ > 工学 > 情報技術 > プログラミング > オブジェクト指向

Wikipedia
ウィキペディアオブジェクト指向の記事があります。
Wikipedia
ウィキペディアオブジェクト指向プログラミングの記事があります。


「オブジェクト」とは[編集]

たとえば、「170.0」という数値データだけでは意図が不明ですが、しかし、たとえばコードで「yamada.sintyou=170」と書けば、意図が、ヤマダ(山田?)氏の身長だと、ハッキリ分かります。

現代では、「オブジェクト」とは、このような記法における、「yamada」の部分のことだけです。

「sintyou」にあたる部分は、アトリビュート(「属性」の意味)とかメンバとかプロパティ(「特性」や「属性」の意味)などといいます。つまり、オブジェクトが持っているデータの定義のことが、アトリビュート(またはプロパティまたはメンバ)です。

また、ヤマダ氏に歩いてもらう処理は(例えばCGなどで、ヤマダ氏の形をしたキャラクターが歩行するとか。)、「yamada.aruki()」などとコードを書けば、同業プログラマーにコードの意図が伝わりやすくなります。

この「yamada.aruki()」というコードの場合、オブジェクトはyamadaヤマダだけです。「aruki()」にあたる部分はメソッド(「方法」という意味)といいます。


もし、ヤマダさんではなく、ロボット1号くん(オブジェクト名は「roboiti」としよう)に歩いてもらうことをオブジェクトの記法で表現するなら、「roboiti.aruki()」というコードになります。

そして、このようなコードでは、「yamada.」の部分が、再利用できます。

もしヤマダ以外に、サトウなどの新しい人員が加わっても、オブジェクトの部分を「satou.」などに変えて、コードを再利用すれば、済むような仕組みになっています。

satou.aruki()」で、サトウさんの歩きをオブジェクトの記法で表現したことになります。

この場合、satouもオブジェクトです。


GUIプログラミングの要素物を「オブジェクト」という流儀もある[編集]

GUIプログラミングは、OSが提供するツールでプログラミングをするのが一般的です。ウィンドウズの場合だと、Visual Basicのようなツールで、GUIプログラミングもできるはずです。

さて、GUIプログラミングをする時、表示対象として、ボタンやテキストボックスやウィンドウなど、いろいろな表示対象を選ぶのですが、この表示対象のことを「オブジェクト」とまとめて言う場合があります。

いちいち「ボタンやテキストボックスやウィンドウなど」などと言うのがメンドウなので、「オブジェクト」というわけです。


「オブジェクト」の定義は人によってバラバラ[編集]

「オブジェクト指向」という言葉が言われ始めたのが1990年代ごろからなので、この時代のWindows95やマッキントッシュ用OSなどのOSの特徴(GUI指向、マルチスレッド作業に対応など)を指して「オブジェクト指向」とか言う人もいますが、しかし、特にパソコン業界では「オブジェクト指向」とは何かの決まりはありません。

単に、90年代のOSを「オブジェクト指向」という人もいる、そういう人もいるってだけです。

90年代後半ごろにC++というプログラミング言語が流行り始めたり、あるいは、Visual Basicなどのwindows用プログラミング言語が流行り始めたこともあり、これらの90年代後半ごろに流行しはじめたプログラム言語のことを「オブジェクト指向」と言ったりする人もいます。

ですが、やはりパソコン業界では結局、「オブジェクト指向」とは何かの決まりはありません。


「オブジェクト指向」対応のプログラム言語はなくてもプログラミングできる[編集]

1990年代の後半ごろから、「オブジェクト指向」に対応したプログラム言語(C++など)が登場し始めました。

1990年代後半の当初、これからは「オブジェクト指向」を活用したプログラミングが主流になると考えられましたが、しかし10数年ほどたても、実際には、「オブジェクト指向」とやらの概念は主流になりませんでした。


そのため、かつて1995年〜2005年ごろは、書店のパソコン書籍コーナーに「オブジェクト指向」を説明した理工書などが多くありましたが、2010年代後半以降の現代では、あまり見かけなくなりました。

なので、このページを読んでる読者は、あまり深く「オブジェクト指向」とやらの意味を考える必要がありません。そのような論説(「オブジェクト指向の言葉の意味を探求すべき」というような論説)は、市場淘汰されました。

「オブジェクト指向」の細かい定義は、人によって、バラバラです。あまり、定義にこだわる必要もありません。

C++(シープラスプラス)などの1990年代後半あたりから普及し始めたプログラム言語に見られる文法(「クラス」機能など)の特徴を説明するのに、「オブジェクト指向」という用語が使われることがあります。

この1995〜2005年ごろの消費者は「きっと、これから、プログラミングに、クラスの概念が必要・ほぼ必須になるだろう」と予想していましたが、しかし現状では、「クラス」機能を使わなくても高度なプログラムができます。

じっさい、C言語には「クラス」機能がないし、C言語で書かれた高度なプログラムは多くあります。リナックスOSの「カーネル」(OSの中核部分)はC言語で書かれています(C++では、カーネルは書かれていません)。

また、他のプログラム言語でも、クラス機能のある言語でも、多くの実用的なプログラムが、クラス機能を使わなくても書かれています。

そして、このC++ですら、1980年代に登場しはじめた当初は「きっと、それまで普及していたC言語に代わって、これから普及していくだろう」と期待されていましたが、しかし2010年代の現代でも、あいかわらず、C++よりもC言語のほうが主流です。


「オブジェクト指向」以前には「構造化」があった[編集]

そもそも、オブジェクト指向よりも前に、「構造化プログラミング」という考えがありました。

構造化プログラミングは、たとえば、「(処理手順を含まない)データは、データどうしで、まとめる」、「(処理手順を含まない)データが何種類もある場合、関連性のあるデータどうしで分類する」、「処理は、処理どうしで、まとめる」(そのため)「処理とデータとは、区別する」、などのような考えかたです。

処理手順の妥当性を吟味するのは大変ですから、なるべく、処理手順を考えなくても作業できるようにする必要があり、そのため、処理手順についてのコード内容と、処理手順をのぞいたデータとを、別々のグループにまとめる、という設計手法があります。

とはいえ、まったく処理手順と、データとが、完全に切り離されいたら、そもそもアクセスできないので、プログラム実行の最初と最後だけで、データと処理手順とを連動させたりしますが・・・。

ともかく、同じ種類のデータをまとめる「構造体」(こうぞうたい、structure)という機能が考えられ、実用化されました。


また、そのプログラムの処理手順を、さらに複数の小さな処理手順(「サブルーチン」「モジュール」)に分解することにより、「プログラムは、サブルーチンの組み合わせである」とする機能も、実用化されました。

なお、C言語などでいう、処理をまとめたもののことを「関数」(function)というのは、このサブルーチンのようなものの事です。もっともサブ(副、予備)があるならメイン(主)があるわけで、C言語では、最初に実行する特別なルーチンの事を「メイン関数」と呼んでいます。

なお、コンピュータで三角関数などの数学的な意味の関数を扱う場合は、例えば「数学関数」などと呼んで、サブルーチンとしての「関数」の用法との混同をふせぐ場合もあります。


この「構造体」でまとめられるデータとは、C言語などの場合、変数データです。処理手順(「関数」)などは、C言語の「構造体」では、まとめられません。

本来、「構造体プログラミング」の考え方では、関数(処理手順)をさらにまとめて構造化してもかまわないハズでしょうが、しかし、C言語はそうなっていません。そのため、後述する「オブジェクト指向」にもとづいた(C言語よりも)新しいプログラム言語で、関数を含めてまとめて構造化する機能が追加されるように、なりました。(後述する「オブジェクト指向」にもとづく言語では、「クラス」という機能を用いて、変数データも関数も、まとめる事ができます。)


さて、ともかく、上述のような構造化プログラミングの利点として、まず、企業などでプログラマーが集団で作業している際に、コード内容が、理解しやすくなります。なぜなら、プログラマーがデータを調整するときは、プログラマーは、データの書かれたコードだけを見れば、済むからです。

そして、このように構造化をして分かりやすくすることによって、もしバグが発生しても、構造が分かりやすいので、バグの箇所も特定しやすく、そのため、修正しやすいという事へと、つながっていきます。

さらに、分業も、しやすくなります。

プログラミング言語である「C言語」そのものの開発では、構造化プログラミングの考えかたも取り入れて、C言語の仕様が決められました。

しかし、構造化プログラミングをすすめているうちに、単にC言語の機能を利用だけでは、まだまだ、構造化が不十分だという事が、分かってきました。

それこそC言語は、複数の種類の変数データを「構造体」として、まとめる事ができるくせに、しかし一方で、複数の種類の関数をまとめる機能すら、C言語には、ありませんでした。

もちろん、個々のソフトウェア会社が、関数をまとめるための関数をコードに記述することで、当面の対応はできます。しかし、個々の企業が自分たちで独自の構造化を行っていては、他社と共同作業を行うのに支障がありますし、大学などの学校教育でも個別の企業の方法については教育できませんし、そのため、ソフトウェア生産の効率が下がってしまいます。


そして、さらに新しいプログラミング手法が提案され、結果的に、(次の節で示しますが)「オブジェクト指向」などとして、新手法が、ひとまとめに呼ばれていきます。

しかし、もしかしたら実態は「C言語が不便なので、新しい言語を考えよう」という側面も、『オブジェクト指向』というフレーズには、あったかもしれません。

こういう実態もあるため、本来なら「構造化」として分類されるべき手法であっても、「オブジェクト指向」に分類されてしまっている手法もあります。

たとえば、「複数の関数(処理手順)どうしをまとめる機能」なんて、なんで『構造化』に分類されずに『オブジェクト指向』に分類されるのか、後世の人間には、いまいち分かりません。

なので、あまり、「オブジェクト指向」の厳密な定義にこだわる必要もありません。


そして、オブジェクトへ[編集]

「オブジェクト指向」の定義は、人によって、バラバラです。あまり、定義にこだわる必要もありません。


よくある「オブジェクト指向」の定義の例として、たとえば、

型から実体を作る

というのがあります。

「クラス」と呼ばれる「設計図」から、実体物に対応するデータを作ろう、とする理念です。

この「実体のデータ」(※ 実体の特性を反映したいデータ)は、一般的には「オブジェクト」や、「インスタンス」と呼ばれています。


プログラミング言語にある「クラス」機能は、あまり名前と内容が、一致していません。なので学習者は、あまり正確な理念内容には、こだわらないほうが、得策でしょう。

「クラス」と聞くと、なんとなく、階層的な分類を思い浮かべるでしょう。しかし、「クラス」をもちいずに、従来の「構造体」でも、階層的な分類は、可能です。結局、データをまとめようとした時点で、個々のデータと、そのデータの集まりとしてのグループという、階層が出来上がってしまいます。


さて、もし、あるデータに、将来的に実体の特性を反映させたい場合、いちばん手軽な方法として、そのデータがなんのためのデータなのかを、コード中で定義してしまう事です。

たとえば、「170.0」という数値データだけでは意図が不明ですが、しかし、たとえばコードで「yamada.sintyou=170」と書けば、意図が、ヤマダ(山田?)氏の身長だと、ハッキリ分かります。もっとも、このような記述は、クラス機能を使わなくても、「構造体」でも可能です。そもそも、このような記法は、もともと、C言語などで構造体を定義するときの記法です。

このため、「そもそもクラス機能は不要では?」とか「構造体の亜流では?」などと考える人たちもいて、その人たちは、C++ではなく(クラス機能のない)C言語でプログラムをしたりするわけです。


さて、「クラス」機能の用語では、この「yamada.sintyou」というコードの場合、オブジェクトはyamadaヤマダだけです。「sintyou」にあたる部分は、アトリビュート(「属性」の意味)とかメンバとかプロパティ(「特性」や「属性」の意味)などといいます。つまり、オブジェクトが持っているデータの定義のことが、アトリビュート(またはプロパティまたはメンバ)です。

また、ヤマダ氏に歩いてもらう処理は(例えばCGなどで、ヤマダ氏の形をした模型が歩行するとか。あるいはヤマダがロボットなら、ロボット歩行のコードになる)、「yamada.aruki()」などとコードを書けば、同業プログラマーにコードの意図が伝わりやすくなります。

この「yamada.aruki()」というコードの場合、オブジェクトはyamadaヤマダだけです。「aruki()」にあたる部分はメソッド(「方法」という意味)といいます。

そして、このようなコードでは、「yamada.」の部分が、再利用できます。

もしヤマダ以外に、サトウなどの新しい人員が加わっても、オブジェクトの部分を「satou.」などに変えて、コードを再利用すれば、済むような仕組みになっています。

もっとも、このような記法(yamada.sintyou)は、けっして「クラス」機能に特有ではありません。「構造体」の時代からある記法です。


結局、用語が統一されていません。そもそも、「オブジェクト指向」時代以前からすでに用語がおかしく、構造化プログラミング時代の「構造体」という用語がオカシイです。英語の日常語でいうstructure(構造)とは、C言語のstrucureは、まったく意味が違います。

もし、変数などのデータをまとめる機能(いまでいう「構造体」)に日常語と似た名前をつけるなら、「グループ」とか名付けるべきだったのでしょう。

結局、そもそも「構造体」という用語そのものが、1960年代ごろのIT業界内部での流行語だった「構造化プログラミング」という用語をもとにつくっただけの、目先の造語でしかありません。1960年ごろに目先の流行語を追って命名しただけのプログラム用語が、2010年代の今だに修正されずに改革されずに続いてるわけです。


このように、プログラムの用語は、発明当時の開発者たちが、あとさき考えずに当時の流行にあわせて用語を命名してたりして、その命名のまま放置されています。けっして物理学や数学などのように、用語が修正されたりしません。

なので、あまり、プログラミング用語の深い意味を考えないほうが、私たち利用者としては得策です。


はたして、実際のいくつかのプログラミング言語にある「クラス」と呼ばれる機能が、はたして「オブジェクト指向」とされる理念を実現できてるかどうかの実情はともかくとして、情報科学・情報工学などではプログラミング言語での「クラス」の構成要素は「オブジェクト」などと呼ばれます。


命令の分類としてのクラス分け[編集]

プログラム言語によっては、「○○を表示せよ」など命令のいくつかが、クラスや構造体のような仕組みによって分類されている場合もあります。

わかりやすいのがJavaScriptという言語で、この言語では、文字表示の命令が「document.write」です。つまり、documentクラスのうちのwriteメソッドとして、文字表示の命令が分類されています。

ほかの言語でも、GUIに関する命令など、最近になって追加されたような命令が、クラスによって分類されている場合も多くあります。

たとえば、一例ですが、ある架空のプログラム言語で、GUIのあるウィンドウを終了させるなら「window.quit()」のように命令する仕組みになっているとしましょう。、windowでウィンドウ関連であることを指定し、quitで終了命令であることを指定し、そしてカッコ内に終了させたいウィンドウの名前を記述する、・・・というような仕組みです。

このように、命令をクラスや構造体の記法で、分類することも、多くの言語であります。

このような場合の「クラス」とは、単に、命令を分類するための手段にすぎません。あまり深遠な意味はないので、必要になったときに、その言語の技術書などで勉強すれば、充分でしょう。

命令を分類するときの用語で、構造体の用語ではなくクラスの用語が用いられるのは、単に、1990〜2005年ごろに普及したプログラム言語での用語の流行が、今でも続いているという、歴史的な慣習にすぎません。

1990年代後半にプログラム言語の文法上で命令を分類しはじめたプログラム言語が流行しはじめて、その少し前の頃、クラス機能のあるC++などが流行していた時代だったので、その「クラス」の用語に合わせただけなのです。


また上述のように、「クラス」という言葉は、それぞれのプログラム言語が好きなように独自の意味で用いていたりしますので、それぞれのプログラム言語ごとに「クラス」の機能が違います。


カプセル化[編集]

Wikipedia
ウィキペディアカプセル化の記事があります。

大規模なソフトウェアであればあるほど、デバッグが大変で煩雑になります。

そのため、関数やデータの中身を秘匿し、コンパイラの静的なレベルでアクセスが不可能になるようにすることがカプセル化の目的です。

あるプログラミング言語が「クラス」という機能を採用している場合、たいてい、その言語では、「クラス」機能をつかって、「カプセル化」的なプログラムも記述できます。

ひょっとしたら、本来なら、プログラミング言語にある「クラス」機能は、本来なら「カプセル」機能と名付けるべきだったのかもしれません。しかし、歴史的な経緯により、「クラス」という名前がついてしまい、学習者の混乱の原因になっています。


こうすると、もし、クラスにバグがないと証明できれば、オブジェクトの使い方が間違っていると分かり、デバッグが楽にできるようになります。

なお、「クラスのデータ(変数)は極力全てを隠すか、書き込み不可にし、関数しか使えないようにするべき」という意見もある。

なお、データをまとめるとき、結局、変数を用意する必要がある。一例として、たとえば山田くんの身長も、佐藤くんの身長も、変数「sintyou」で扱う・・・というように。

なので、クラスのデータを隠すとは、つまり、そのデータ名の変数を隠すことに、つながる。


さて、単に変数データをまとめるだけなら、「構造体」(structure)という、もともとは変数データをまとめるだけに特化した機能が、クラス発明の以前から、存在していた。

なお、言語によっては、独立した「構造体」機能がない言語もある。構造体のない言語の場合、「クラス」機能で「構造体」機能と同じことをする言語もあり、そのため、「クラス」が「構造体」を代用するプログラム言語の場合、原則的に「クラス」宣言だけではカプセル化を行わない仕様になっている。

このように、言語によって、「クラス」機能では、原則的にカプセル化を行う仕様になってるか、そうでないかが、異なる。


そのため、プログラマーは、けっして、言語によるクラス機能の自動設定まかせに、カプセル化をするべきではないだろう。 なるべく明示的に、カプセル化をしたいかどうかを、コード中に書けるようにするのが、合理的である(他の言語に移植するときにも、作業者が理解しやすい)。

このような、カプセル化の有無の明示化の目的のため、あるデータの修飾に「public」(パブリック)または「private」(プライベート)といったアクセス指定子をつけることによって、そのデータをカプセル化するか、しないかを設定できるようになっている言語も多い。


一般に、あるデータの修飾に「public」(パブリック)というアクセス指定子をつけることによって、「そのデータを、カプセル化しない」(「隠さないで、他の関数から」、「アクセスできるぞ、他の関数からは」)と宣言した事になります。

一方、あるデータの修飾に「private」(プライベート)というアクセス指定子をつけることによって、「そのデータを、カプセル化する」(「隠せ、他の関数からは」、「アクセスさせないぞ、他の関数からは」)と宣言した事になります。


なお、アクセス指定子はクラス内で、それぞれのデータや変数に対して書かれます。そのように書かれたアクセス指定子により、アクセス指定をされる対象は、クラス自身ではなく、クラスのなかに書かれているデータとクラスの中に書かれている関数が、アクセス指定をされるのです。

クラスのなかで、クラス内にある、それぞれのデータごとに、public(公開)にするか、それともprivate(非公開)にするかを、アクセス指定子により決定します。

一般には、クラス内のごく一部のデータと一部の関数だけをpublicで公開にして、クラス外の他の関数とのやりとりをできるようにして、いっぽう、クラス外との直接のやりとりに必要の無い、その他のデータはprivateで非公開にすることにより、誤ったプログラムなどによる書き換えなどを防ぐという工夫をする、・・・という手法が取られる手法が、多くあります。(プログラム入門書の書籍などでも、そのように記載される事が多い。)


さて、プログラム言語の種類によって、アクセス権限を指定しない場合に「カプセル化をするか」「カプセル化をしないか」が、異なります。

それぞれ一長一短であり、どちらが良いとかは、決められません。

もし、ある言語が、アクセス指定子をつけない場合に、自動的にカプセル化をする仕組みの場合、欠点として、学習者がカプセル化の仕組みを理解するまでは、なかなか、動作するコードを書きづらくなる、・・・という欠点もあります。

このため、入門用の言語などでは、アクセス指定子のない場合にはカプセル化をしないという仕様にしている場合もあります。

いっぽう、このような、アクセス指定をしない場合にデータ等を隠さない言語は、コードミスだが動作してしまうバグなどの際に、本来なら隠したい処理に客先などがアクセスしてしまう、というような事故なども、起こりやすくなるでしょう。

もし、コードミスがなければ、アクセス指定子のない場合に自動的にカプセル化をしてもしなくても、どちらでも構わないでしょうが、しかし現実には、プログラマーがコードミスをしない言語なんて、ありえません。


「もしアクセス指定子のない場合に、カプセル化をする仕様か、しない仕様か?」という仕様は、コードミスの観点から見れば、つまり、 「もし、うっかりミスで、アクセス指定子をつけ忘れた場合に、カプセル化をする仕様なのか、しない仕様なのか?」という仕様になりますので、つまり、コード中の企業秘密などの扱いかたに、つながるわけです。

このため、ある程度、専門IT技術者むけの言語の場合、企業秘密を守れる仕様であるべきですから、おそらく、その言語では、「アクセス指定子のない場合に、カプセル化をする仕様」でしょう。じっさい、「C++」言語が、そのような仕組みです。

そもそも、もともとカプセル化をするために、「クラス」機能が開発されたという経緯もあります。(C言語では、構造体にはアクセス指定子をつけられませんので、カプセル化をできません。)

プログラミング言語によっては、大規模なプログラムを開発するためのアクセス権限を指定しない場合、自動的に他の関数からは隠される仕様になっている事も、多くあります。


継承[編集]

クラス(かりにクラスGとする)を作ったときに、それと似た仕組みの他のクラス(かりにクラスHとする)も、作る必要があったとしましょう。このようなとき、わざわざクラスHに、クラスGと同じ内容のコードを書かなくても、クラスGと違う内容だけを指定すれば、クラス Hを作成できるような仕組みで、クラスを作成できるようにする機能のことを「継承」(けいしょう、inheritance)といいます。

裏を返せば、右クリックによるコピー&ペーストで記述しても構わないなら、つまり、クラスHを作る時に、クラスGと同じ内容のコードを実際にコード上に(コピー&ペーストで)書いてもかまわないなら、わざわざ「継承」の仕組みをつかう必要はありません。

このため、小規模なプログラムでは、「継承」の仕組みをつかうメリットは、少ないでしょうし、むしろ、継承もとを探す手間を考えれば、小規模なプログラムでは、むやみやたらに継承をつかうべきではないかもしれません。

このような考えのためか、プログラム言語によっては、継承の機能はないプログラム言語もあります。(たとえばC言語には、そもそも「継承」の機能はない。なお、C言語には、「クラス」の機能もない。)


構造体を継承できるかどうかは、プログラム言語ごとに異なります。C++では構造体を継承できます。

下記では、特にことわらないかぎり、クラスの継承について、記述します。


さて、継承の機能のある言語の場合、もしクラスGから派生した似た内容のクラスが、クラスHのほかにも、クラスJ、クラスK、クラスL、クラスM、クラスP、・・・などと大量にあるような場合なら、継承によって、手間を大幅に省けるかもしれません。

しかし、そうでない場合なら、かならずしも「継承」にこだわる必要は、ないかもしれません。似たクラスの数が、それほど多くない場合、いっそコピー&ペーストで実際にコードをコピーしてしまうことにより、「継承」を使わないのも、ひとつの手法でしょう。


なお、「継承」という場合、継承元となったクラスは、それ自身でも単独でクラスと機能するのが通常です。

いっぽう、もし、元となったコードが、それ自身が単独ではクラスとして機能しない場合は、例えば「テンプレート」や「抽象クラス」などと呼び、通常のクラスとは区別します。

言語によって、派生もとのクラスの呼び方と、派生先のクラスの呼び方が、異なっています。おおむね、次のような組み合わせになっています。


継承に関するクラスの名前
派生もとのクラス 派生さきのクラス
基底クラス 派生クラス
親クラス 子クラス
スーパークラス サブクラス

つまり、派生元に「基底クラス」という言い方を使うなら、派生先に「派生クラス」という言い方を使います。

つまり、派生元に「親クラス」という言い方を使うなら、派生先に「子クラス」という言い方を使います。


言語によって、上記の呼び方の表のうちの、どの言い方が主流かが、異なっています。それぞれの言語で主流になっている呼び方を、してください。

また、継承時のカプセル化にかんする仕様が、言語によって、異なっています。

このため、「基底クラス」と言ったときと、「親クラス」と言った時とで、聞き手によっては「継承にかんする仕様が異なっているんだろう」とイメージする人も、多いでしょう。

なので、それぞれの言語で主流になっている呼び方を、してください。


なお、一部の言語では、クラスの宣言時に、そのクラスを継承することを禁止する機能をつけることもでき、JavaやC#などが、そのような継承禁止宣言の機能を取り入れています。ですが、あまり他のプログラム言語には、普及していません。Javaの場合は final ファイナルという修飾子で、C#の場合は「sealed」シールド(封印された という意味)という修飾子をつけ、継承禁止を宣言します。


関数すらクラス化するプログラム言語もある[編集]

C言語などでいう「関数」は、手続きをまとめたものです。

さて、オラクル社のJavaや、マイクロソフト社のVisual C++ などのVisual ◯◯やC#では、手続きをまとめたものを定義するときに、「class」という宣言を使います。これらJavaやC♯では、もしプログラマーが関数を使用したいときに「class」という構文をつかわないと、そもそも関数を宣言できず、関数を使用できません。

それらのプログラム言語では、どうも、関数すらクラスとして分類しようという方針のようです。

ですが、ほかの多くのプログラム言語では、採用されてない仕様ですので、分かならくても悩まなくても良いです。

このJavaやVisual ◯◯などの、関数がclassによって定義される仕様の欠点として、簡単な処理を書きたいだけの場合ですらコードが長くなる、という不便な欠陥があります。

たとえば、「Hello」という文章を表示したい場合、 もしJavaなら、

(Javaの場合)

public class クラス名 {
    public static void main(String[] args){
        System.out.println("Hello");
    }
}

という、かなり長い文になります。

マイクロソフト社のVisual ◯◯も、同様に長くなる傾向です。たとえばVisual C♯(シーシャープ)および単なる「C♯」では、

(C♯の場合)

class クラス名
  {
    static void Main() {
       Console.WriteLine("Hello");
    }
  }

というふうな感じになります。


これらJavaやC♯のプログラム言語の入門書を読んでも、結局、クラスについて、2度、説明することになります。まず、書籍冒頭での、C言語でいう関数としての機能の「クラス」の説明するほかに、書籍の中盤のほうで、従来のC++でのクラスの機能をもつ別内容の「クラス」について説明するというように、クラスについて2度説明しなおす羽目になります。

なので、関数とクラスとを同一視することは、けっして普遍的な原理ではなくて、いちぶの企業の提供するプログラム言語の仕様にすぎません。


また、上記のような関数の分類をする文法で、構造体による分類ではなく、クラスを使って分類するという文法にされている理由も、単に歴史的な偶然にすぎないでしょう。単に、マイクロソフト社などの大手の会社が、そのような文法を採用した、というだけの事です。


オブジェクト型[編集]

C#(シー シャープ)などの いくつかの言語で採用されている「オブジェクト型」という型は、一般的な値型とは考え方が違います。

値型では、

a = 2
b = 3
a = b
a = 4

とすると、a = 4、b = 3 になります。しかし、オブジェクト型では、a = 4、b = 4 となります。 こうなる理由は、値型とオブジェクト型の仕組みが違うからです。

値型では、変数自体が値を持っているという考え方をします。

値型の場合

しかし、オブジェクト型の場合は違い、メモリへのポインタという考え方です。

オブジェクト型の場合

メモリのどこかへオブジェクトが作られ、オブジェクト名というのはリファレンス名であり、メモリを参照しているだけである。

これがオブジェクト型と値型の違いです。これをしっかり把握しておかないと、あとで混乱してしまうことになります。