前回は、構造体を説明しました。今回は、いよいよクラスです。

今、殆どのプログラミング言語(C#以外)でもクラスを使ってプログラミングが出来ます。
ここ十数年、長く使われ続けているクラスは、プログラミングを行う上で重要な存在です。

クラスは、抽象化した構造を作るのに向いています。モノを作るために必要な設計図みたいなものです。例えば、車のベースの設計図があるとしたら、それから様々な車種の設計図を派生して作れるようなものに近いです。設計図(クラス)から実物になったものをオブジェクトインスタンスと呼んだりします。

クラスの利用は、変数や関数をグループ化して独自の型を作成できます。

Windows上で役に立つツールを手軽に作りたい!となると、.Net Frameworkを利用することになります。.Netは、Windowsを操作するDLL(API)をラップしたクラスがたくさんあります。それにはある程度クラスは避けて通れません。しかし、最初からすべて理解することは難しいと思います。でも、「なんちゃってプログラム」でも構文エラーにならなければ動いてしまいます(^∀^)

最初は、いろいろクラスに触れながら「どう動く」を理解していけばよいのです。
以下、クラスの代表的な3つの機能を紹介していきます。

・カプセル化(隠ぺい化)

内部の動きを隠すことができる。⇒利用者は、やりたいことの関数を呼べば、内部の動きを気にする必要がない。
外部から内部変数の直接な変更をできないようにして、主コードと分離ができる。⇒汎用性が高くなる。

・継承

親(基底クラス)の属性/関数/イベントを受け継いだ子(継承クラス)が作れる。

・多態性

基底クラスのオブジェクトに継承したクラスのオブジェクトを代入し、振る舞いを変化させる「ポリモーフィズム(多態性)」が使える。

他にも、クラスにはたくさんの機能があります。何ページにもなる本があるくらいですから。
オブジェクト指向(クラス及び構造体)プログラミングは、追々進めていきましょう。

クラスの構文から見ていきましょう。

クラスの構造

アクセス修飾子 Class クラス名 {
  内部変数
 イベント定義  プロパティ定義  メソッド定義etc }

クラスの利用方法


C#

class StudyClass
    {
        public class pet
        {
            public enum syurui {inu,neko,saru};
            private syurui m_syurui;
            private string m_petname=string.Empty;
            private int m_hosu=0;

            //【プロパティ】
            // ペットの名前
            public string PetName {
                set { this.m_petname = value; }
                get { return this.m_petname; }
            }
            public int TotalHosu
            {
                get { return this.m_hosu; }
            }

            //【コンストラクタ】
            public pet(syurui syu)
            {
                this.m_syurui = syu;
            }

            //【メソッド】
            public string Nakigoe() {
                string ret = "...";

                switch (this.m_syurui){
                    case syurui.inu : ret = "ワンワン";break;
                    case syurui.neko: ret = "にゃ~"; break;
                    case syurui.saru: ret = "うききー"; break;
                }

                return ret;
            }
            public void Sanpo(int addHosu)
            {
                this.m_hosu += addHosu;    
            }
        }

        static void Main(string[] args)
        {
            pet p = new pet(pet.syurui.inu);
            p.PetName = "ぽち";
            p.Sanpo(50);
            p.Sanpo(100);
            System.Console.WriteLine("{0}は、{1}歩あるいて、{2}と鳴いた。", p.PetName,p.TotalHosu, p.Nakigoe());
            pet p2 = new pet(pet.syurui.neko);
            p2.PetName = "ミケ";
            p2.Sanpo(10);
            System.Console.WriteLine("{0}は、{1}歩あるいて、{2}と鳴いた。", p2.PetName, p2.TotalHosu, p2.Nakigoe());
            System.Console.ReadLine();
        }
    }

出力結果

ぽちは、150歩あるいて、ワンワンと鳴いた。
ミケは、10歩あるいて、にゃ~と鳴いた。


まずは、StudyClassクラス内にclass Petというクラスがあります。クラスの中にクラスをいくらでも宣言できます。(クラスの入れ子は継承ではありません)
classの文字の前にあるpublicというアクセス修飾子がありますね。アクセス修飾子は、以下の通りです。

アクセス修飾子 説明
public どこからでもクラスを利用可能
private 同じクラス内であれば利用可能。それ以外はアクセスできない。
protected 同じクラス内または、派生クラスであれば利用可能。
internal 同じアプリ内(アセンブリ)なら利用可能。

Petクラスはpublicなので、StudyClassクラス内のMain関数からPetクラスが利用できます。

Petクラス内では、enumという列挙体を定義しています。列挙体は、種類などをプログラム上でわかりやすく名前付けして管理するのに便利です。変数の型にしたり、関数で引き渡せたりもできます。switch文などで、文字列や数字を使うより不具合の発生を抑えることが期待できます。

列挙体の下あたり、Petクラス内でしか使えない内部変数をprivateをつけています。メンバー変数(フィールド)ともいいます。メンバーとは、内部のものを表し関数はメンバーメソッドとも言います。

外部からは、プロパティ(属性)を経由して、内部変数にアクセスできるようにしています。プロパティは、外部から取得するときは、get内に返すものを記述し、set内では、代入されたvalueという引数を使い内部変数に入れます。getのみ記述した場合、読み取り(ReadOnly)しかできないようにすることもできます。内部変数をpublicにすれば直接外部から代入できますが、変数の隠蔽やset何でひと処理(変換など)加えて内部変数に代入することもできます。プロパティで内部変数を隠蔽(カプセル化)させることにより汎用性の高いクラスが出来上がります。

構造体と同じく、外部でnewされた時に呼び出されるコンストラクタも定義しいます。

公開メソッド(関数)は、Nakigoe()でペットの種類(syurui)により鳴き声(string)を返すようにしています。Sanpo(int)では、内部の歩数(m_hosu)を加算しています。

Mainメソッド内では、Petクラスをnewしてオブジェクトを生成しています。変数名にドット(.)を使いアクセス公開されているプロパティや関数を使っています。クラスを利用するだけなら簡単なものだと理解して頂けたでしょうか?

静的と動的

ここでようやく何度も登場していたMainメソッドに付いているstatic修飾子について説明しましょう。
staticとは、静的という意味で変数(フィールド)やメソッドに付けることが出来ます。
このようにしておくと、クラスをインスタンス生成しなくても(newしなくても)、その変数やメソッドがいきなり使えます。パソコン側では、プログラムが読み込まれた時に変数やメソッドがメモリ領域に確保されます。反対に、動的はインスタンスを生成して変数・メソッドを利用することです。

プログラムがロードされたあとすぐにMainメソッドが使用できるワケです。

すべてstaticにすればいいと思いますが、同じクラスの複数インスタンスを生成すると、メモリの同じstatic領域にアクセスしにいくため、別々に変数を管理することが出来ません。別々に管理したいときもありますし、メモリもプログラムが実行されている間は使いっぱなしになってしまいます。色々な場面で使い分けていきましょう。

C#の例

namespace StudyStatic
{
    class Program
    {
        class Hoge
        {
            public static string test = "これは静的です!";
        }
        static void Main(string[] args)
        {
            Console.WriteLine(Hoge.test);
            Hoge.test = "はい、わかりました。";
            Console.WriteLine(Hoge.test);
            Console.ReadLine();
        }
    }
}

結果

これは静的です!
はい、わかりました。

インスタンス(new)せずに、Hogeクラスの変数を利用している例です。あまり美しくないソースですが・・・(汗)


次回は、クラスで覚えておかないといけない継承を説明します。
スポンサードリンク