Ta-kaku.jp Tools
Update 2010/02/06
技術メモ内容
トップページ
ハードやソフトの技術メモです。 ほとんど、個人の備忘録のレベルですので高度なことは書かれていません。 皆様に少しでもお役に立てれば幸いです。
MENU
3.Class概念
サイト更新情報
2008/10/18
「Ta-kaku Tools 住所検索・郵便番号検索・事業所名検索・駅検索・電話局番検索」を Ver2.202 にリビジョンアップしました。
更新内容は以下の通りです。
・「xxx1丁目」の様に「全角の数字」と「丁目」が続いている文字列が入力されると検索できない事がある不具合を改修しました。
2008/10/01
Ta-kaku Tools Whois検索 Ver1.000をリリースしました。
2008/09/30
「Ta-kaku Tools 住所検索・郵便番号検索・駅検索・電話番号(局番)検索 」を Ver2.201 にリビジョンアップしました。
更新内容は以下の通りです。
・電話番号(局番)検索機能を正式版にしました。 ・無効な数値に対して住所の検索を行っていた処理を改善しました。 ・局番0120指定でGoogleMapがおかしな場所を示していた不具合を修正しました。 ・「東京駅駅」のように入力されると、関係の無いデータが出力される不具合を修正しました。
過去の情報
関連キーワード
技術メモ インデックス
カテゴリーを選択してください。
インストール
プログラミング言語
マークアップ言語
データベース言語
スクリプト言語
MS-Office
その他
Webアプリケーション
の開発方法
3.Class概念 技術メモ
追加日時の新しい方から掲載しています。
第3章 Classの概念について
登録日:2006/09/19   分類:Webシステム
前書き
    よくClassは難しい、分かりにくい等の声が聞かれますが、
    前章の構造体の概念を正しく理解されている方には、容易に理解できる概念です。
    VBで頻繁に登場する、「プロパティ」や「メゾッド」も正にClassのメンバを指して
    います。
    "class" という言葉は、既に、第1章のCSSを説明した所にも登場しています。
    現在のプログラマーの大半が、実は、意識する事無く "class" を利用しています。

    注意
        この章のサンプルに使用しているクラスの定義方法は、PHP や JavaScript で
        扱う Class の形式と異なるものも含まれています。

目的
    Class には、機能のブラックボックス化,変数や関数のスコープ範囲の明確化,
    それらに伴う、グローバル変数による汚染の防止などの効果があります。
    ここでは、これらの特徴にスポットを当てて、Class の概念を整理したいと思います。

目次
    1.カプセル化とは
    2.オブジェクト指向とは
    3.クラス定義とは
    4.派生クラスとは
    5.クラスを推奨する理由
    6.クラス定義の比較例

1.カプセル化とは
    1-1.カプセル化とは、機能をブラックボックス化する概念

        カプセル化とは文字通り「閉じ込める」ことを意味しています。
        カプセル化すると、外部からの直接的な影響を受けなくなります。
        また、内部データの隠蔽の役割も担っています。

                +---------------------+             内部の変数に対する代入など
                |内部の変数は、外部か |             意図しない代入を防ぐ事ができる。
                |らアクセスすることが | × <------- また、内部の公開したくない
                |できない。           |             データの隠蔽が可能になる。
                +---------------------+
                カプセル化された部分

        カプセル化された機能には、I/F(インターフェース)のみが外部に公開されます。
        プログラマーは、内部の仕組みを意識する必要がありません。

                +---------------------+
                |                     |             通常、カプセル内にデータを隠蔽し、
        IN ---> |中はブラックボックス | ---> OUT    公開されたI/Fとしてを介して
                |                     |             データへアクセスします。
                +---------------------+
                カプセル化された部分

    1-2.関数のスコープ

        VBの場合は、関数のスコープを明示的に定義する方法として、ファイルの分離
        があります。
        ファイルを分離すると、基本的に別ファイルの内容を閲覧できなくなります。
        例えば、aaa.bas の内容を bbb.bas からは見る事ができません。
        これは、ファイル単位のスコープという考え方になります。

        しかしC系では、ファイルの分離は意味がありません。
        VBの様に、それぞれのモジュールで隔離したい場合は、カプセル化する必要が
        あります。
        カプセル化すると、ファイル単位はもちろん、ファイル内でさらにスコープを
        指定することが可能になります。

            +----------------------+
            |   +--------------+   |
            |   | aaa(){ ... } |...|... カプセル化   aaa() は bbb() を自由に
            |   | bbb(){ ... } |   |                 呼び出すことができるが、
            |   +--------------+   |                 ccc() や ddd() はできない。
            |   +--------------+   |                 (と思ってください)
            |   | ccc(){ ... } |...|... カプセル化
            |   | ddd(){ ... } |   |
            |   +--------------+   |
            +----------------------+

        共通関数では、関数をモジュール群として、ある特定の「ファイル」に集めて
        いるだけでした。
        これは、コンパイルレベルでは、何の意味もありません。
        カプセル化では、関数を「ファイル」に集めるのではなく「スコープ内部」に集めて、
        コンパイルレベルで分離をさせる事ができます。

    1-3.関数名重複問題の解決

        共通関数の場合は、システム内の全ての関数名がユニークでなければいけませんでした。
        これは、大規模開発を行なう場合に弊害になる仕様で、プログラマー達は常に関数名に
        注意を払う必要がありました。

            Aさんのファイル            Bさんのファイル
            --- sample1.c --->         --- sample2.c --->
            sub_fnc1() ... OK          sub_fnc4() ... OK
            sub_fnc2() ... NG          sub_fnc2() ... NG    ... 同一 exe でリンクすると
            sub_fnc3() ... NG          sub_fnc3() ... NG        エラーになる
            <--- sample1.c ---         <--- sample2.c ---

        一方、カプセル化されたスコープ内では、関数名に注意を払う必要がなくなりました。

            Aさんのファイル            Bさんのファイル
            --- sample1.c --->         --- sample2.c --->
            +-カプセル A-------+       +-カプセル B-------+
            |sub_fnc1() ... OK |       |sub_fnc4() ... OK |
            |sub_fnc2() ... OK |       |sub_fnc2() ... OK | ... 同一 exe でリンクしても
            |sub_fnc3() ... OK |       |sub_fnc3() ... OK |     影響が無い
            +------------------+       +------------------+
            <--- sample1.c ---         <--- sample2.c ---

2.オブジェクト指向とは
    2-1.型と実装

        「型」とは、プログラムが使用する「入れ物」の大きさを表します。
        その「大きさ」とは、使いたい物理メモリの量を指します。

        一方、「実装」とは、型にあわせて実際に物理メモリを確保する事を指します。
        オブジェクトも物理メモリを必要とします、オブジェクト用の物理メモリを確保
        する事を「インスタンスを生成する」と言います。

    2-2.オブジェクト指向とは

        ソフトウェアの世界での「オブジェクト」とは、機能が「実装」された状態を
        指しています。
        すなわち、既にメモリにプログラムがロードされている状態です。
        これは、「物が存在する」という感覚で「オブジェクト」という言葉が使用されます。

        オブジェクト指向とは、予め「オブジェクト」を存在させておき、存在しないものに
        処理をさせようとして、致命的エラーなどを発生させないようにした考え方です。

        従って、「インスタンスのメモリ領域を確保する考え方」などと言われます。

        オブジェクトはクラスをインスタンス化することにより生成します。
        クラス ⇒ インスタンス化 ⇒ オブジェクト

            インスタンス化 = インスタンスを生成する
            オブジェクト = インスタンス

3.クラス定義とは

    3-1.クラス定義は、カプセル化を実現する宣言です。

        class SAMPLE    ... クラスの宣言
        {               ... クラス型スコープの開始
            宣言
        };              ... クラス型スコープの終了

        この記述は、前章の構造体の定義に似ています。
        構造体の struct が class に変わっただけです。

        それでは、このクラスに変数のみを宣言してみます。
        (通常は、このような使い方はしません。
         Cコンパイラではワーニングエラーになります。)

        class SAMPLE
        {
            int   a;         ... メンバの宣言
            long  b;
            float c;
        };
        ここまでの定義は、構造体の機能と全く同じになります。

        構造体と異なり、クラスの場合は、更に関数自体もメンバとして宣言する事が
        できます。
        それでは、このクラスに関数を宣言してみます。

        class SAMPLE
        {
            int   a;
            long  b;
            float c;

            int sample1()    ... メンバの宣言
            {
                c = a + b;
            }
        };

        sample1() は、class SAMPLE のスコープ内部のみ使用可能です。
        同様に更に関数を追加する事により、スコープに閉じられた関数群を宣言する
        事ができます。

        class SAMPLE
        {
            int   a;
            long  b;
            float c;

            int sample1()
            {
                this->c = this->a + this->b;
            }
            int sample2()
            {
                this->b = this->c + this->a;
                this->sample1();
            }
            int sample3()
            {
                this->a = this->b + this->c;
                this->sample2();
            }
        };

    3-2.プロパティとメゾッド

        VBでお馴染みの CommandButton を思い浮かべてください ... 。

        ボタンの大きさやボタンに表示する文字列の属性は、
        「プロパティ」と呼ばれます。
        ボタンをクリックすると、イベントが発生して、
        イベントに応じた関数が実行されます。
        実行される関数は、「メゾッド」と呼ばれます。
        いずれも、フォームに貼り付けた CommandButton 
        オブジェクトのメンバになります。

        VBの開発環境がある場合は、以下の操作でこの状態が確認できます。

        準備として、フォームの上に CommandButton オブジェクト
        を一つ貼り付けて、
        ボタンオブジェクトをダブルクリックして、
        Command1_Click() を生成してください。

        次に、メニューの [表示]-[オブジェクトブラウザ]を選択します。
        オブジェクトブラウザの上のコンボボックスから、
        プロジェクト(Project1など)を選択します。
        すると、「クラス」と書かれたペインにフォームの
        オブジェクト名(Form1など)が表示されます。
        そのオブジェクト名を選択すると、フォームのメンバが表示されます。

        先ほど生成した関数は、クラス Form1 にメンバ関数 Command1_Click() 
        を追加したものになります。
        これをクラス定義すると、以下のようになります。
        (以下は、想像です。実際はどうなっているか公開されていません)

        <注意> 雰囲気だけ理解してください ...
        class Form1::Form                       ... クラス
        {
            CString Caption = "Form1";          ... プロパティ
                :
                : 略
                :

            founction Command1_Click()          ... メゾッド
            {
                ここにコードが追加される
            }

            Command1 = new CommandButton;       ... インスタンス
        };

        上記の様に、クラス内部の変数を「プロパティ」、
        関数を「メゾッド」と言います。

4.インヘリタンスとは

    インヘリタンスとは、クラスの継承を意味します。
    クラスの継承により、既存のクラス定義から(既存のクラスを再利用し)、
    新たなクラスを定義します。
    継承されたクラスは、派生クラスとも呼ばれます。

    既存のクラス定義 ⇒ 継承(インヘリタンス) ⇒ 新たなクラスを定義(派生クラス)

    4-1.インヘリタンスの概念

        たとえば、Aさんの作成した Class A という「機能がフィックスされた共通クラス」
        が存在していたとします。

            Aさんの作成した Class A
            +-Class A-------------------+
            |in buf;     ... プロパティ |
            |sub_fnc1(); ... メゾッド   |
            |sub_fnc2(); ... メゾッド   |
            |sub_fnc3(); ... メゾッド   |
            +---------------------------+

        他のプログラマーは、sub_fnc1() sub_fnc2() などの機能が必要な場合、
        Class A を使用すれば解決します。
        しかし、Class A の種類(たとえばDBアクセスなど)に属する、
        共通的でない sub_fnc4() を作成する必要がある場合、
        他のプログラマーは、Class A を継承した Class B を作成することで論理構造を 
        整理しつつ、sub_fnc1() sub_fnc2() sub_fnc4() を使用する事が可能になります。

            Class A の機能を拡張した Class B
           +--Class B--------------------+  ... Class B が派生クラス
           |+-Class A-------------------+|  ... Class A が基底クラス
           ||in buf;                    ||
           ||sub_fnc1(); ... 利用したい ||
           ||sub_fnc2(); ... 利用したい ||
           ||sub_fnc3();                ||
           |+---------------------------+|
           | sub_fnc4(); ... 新規作成    |
           +-----------------------------+

    4-2.オーバーライドとは

        オーバーライドとは、再定義を意味しています。

        クラスの中では、関数名を意識させないという概念は、派生クラスにも踏襲
        されています。
        クラスを派生した場合に、基底クラスのメンバ関数と同名の関数を作成したい
        場合があります。
        同名のメンバ関数を宣言した場合、派生クラス側の関数が有効になります。

        これを、オーバーライドと言います。

            Class A の機能を拡張した Class B
           +--Class B-----------------------+  ... Class B が派生クラス
           |+-Class A----------------------+|  ... Class A が基底クラス
           ||in buf;                       ||
           ||sub_fnc1(); ... 使用されない  ||
           ||sub_fnc2();                   ||
           ||sub_fnc3();                   ||
           |+------------------------------+|
           | sub_fnc1(); ... オーバーライド |
           +--------------------------------+

5.クラスを推奨する訳

    5-1.クラスの利点と欠点

        利点
            ?機能のブラックボックス化ができる。
            ?変数や関数のスコープ範囲を明確化できる。
            ?グローバル変数による汚染をある程度防止できる。
            ?関数名の重複問題を解決できる。
            ?変数と関数をセットでオブジェクト化できる。
            ?継承による機能拡張が容易。
            ?既存コードの再利用性が向上する。

        欠点
            ?アプリケーションのデータ構造設計が難しくなる。
            ?コーティングが若干難しくなる。

        以上のように、クラスを採用する利点は、欠点を十分に払拭するものです。
        クラスを使用したコーディングに慣れると、クラス無しのコーディングに戻る事
        はできないでしょう。
        たとえば、クラスを使用しない純粋なC言語で、フォームにボタンを追加しようと
        思ったら大変な事になります。
        クラスを利用できれば、フォームのクラスとボタンのクラスを継承するだけで済みます。

        クラスでは、プロパティとメゾッドが同一スコープに閉じられている為、
        メンバの所在が明確になります。
        誤って、別のプロパティに値を代入してしまう不具合が少なくなります。

        作成した関数は、ぜひクラスのメンバとしてください。
        明確に分かれた機能は、再利用が容易になります。

6.クラス定義の比較例

    6-1.CSSの場合

        div.SAMPLE
        {
            color: red;
        }

    6-2.JavaScriptの場合

        なし ... JavaScriptでは、クラス定義無しにメゾッドやインスタンスが使用できる。

    6-3.PHPの場合

        class SAMPLE
        {
            var $aaa;

            function add_item ($pWork)
            {
               $this->aaa += $pWork;
            }
        }

    以上のように、各言語によってクラスの定義方法は異なります。
    CSSの場合は、C系から派生している言語では無い為、記述方法が根本的に異なります。
    JavaScriptの場合は、クラスの定義そのものが存在しません。
    しかし、既存の関数を利用してインスタンスを生成させたり、クラスのメゾッドとして
    扱ったりできます。

最後に
    JavaScriptとPHPのクラスの使用方法については、「第4章 JAVAScriptについて」
    「第5章 PHPについて」で詳しく説明します。

参考

---

・本ページの内容は、Ta-kakuが住所検索のページを作成する際に独自で調査した内容を
  講座的にまとめたものです。

・記述に誤りがある場合は、訂正して読み替えてください。

・技術的な内容にはお答えできませんので、予めご了承ください。
PR