C#のクラス、フィールド、メソッド、コンストラクタ、プロパティの作成

C#でクラスを作成してみます。

C#はオブジェクト指向言語なのでクラスを作成しそこにフィールドとメソッドを定義してオブジェクトを作成します。

フィールドはそのオブジェクトが保持しておく値、メソッドがそのオブジェクトが出来る操作ですね。

スクリプトの作成はUnity付属のMonodevelopを使用して作成していきます。

作成したクラスはMainClassというUnityのMonoBehaviourクラスを継承したクラスで実行する形を取っていきます。

UnityでC#のスクリプトをLearn1_1というファイル名で作成すると

というスクリプトがデフォルトで作成されます。

Unityの場合はMonoBehaviourクラスを継承してLearn1_1クラスが作成されるので、MonoBehaviourクラスで定義されているStartメソッドやUpdateメソッドを

子クラスであるLearn1_1でも使えるんですね。

継承はまた別の記事でやりますのでそれまで置いておきます。

スポンサーリンク

C#のクラスの作成の仕方

通常のC#クラスを作るとすれば

と作成し外部のスクリプトから使用します。

名前空間にクラスを入れる

C#では名前空間と呼ばれるものがあります。

この名前空間はJavaで言えばパッケージと同じようなものでその名前空間にクラスを入れて同一クラスでも名前空間で分けてクラス定義する場合は便利です。

あえて同じ名前のクラスを作成し名前空間で分けて使うというよりも複数人で開発したクラスを統合する時のクラス名の競合の回避に使うという感じですね。

この名前空間はさきほどのスクリプトでも出ていて、

の部分でUnityEngine名前空間に定義されているクラスをUnityEngineの部分を省略して使用する事が出来るようにしています。

その為usingディレクティブを使わなければ

↑のように記述出来ますね。

では、Learn1_1をLearn1という名前空間に定義しそれを使ってみます。

namespaceに続けてLearn1を記述し、その中にクラスを内包する形で定義します。

このLearn1_1クラスを外部クラスから使ってみます。

Learn1_1クラスをインスタンス化(インスタンス化については後述します)していますが、Learn1_1クラスはLearn1名前空間で定義されているので、

using Learn1;

と記述しLearn1.Learn1_1と記述しなくてもいいようにしています。

アクセス修飾子

さきほどのクラス定義の部分に出てきたpublicの部分がアクセス修飾子ですね。

publicは他のアセンブリ、他のクラスからもアクセス出来ます。

privateは自身のクラスからしかアクセス出来ません。

protectedは自身か自身を継承した子クラスからしかアクセス出来ません。

他にinternalという別のアセンブリからはアクセス出来ないというのもあるみたいですね。

メソッド定義

クラスには操作を担当するメソッドがあります。

Learn1_2クラスにTalkとRunメソッドを記述します。

メソッドにも同じようにアクセス修飾子を付け外部アセンブリ、クラスからのアクセスの制限を加えています。

↑のようにTalkにはstatic修飾子を付けています。

これは静的という意味でクラスをインスタンス化せずに実行出来るようになります。

voidは戻り値の型で何らかの処理をして値や参照をメソッドを呼び出したところに返す必要がある時のその値の型を指定します。

それでは実際にLearn1_2クラスのTalkとRunメソッドを呼び出してみましょう。

Learn1_2クラスのメソッドを呼び出す新しいMainClassクラスを作成します。

Talkは静的メソッドなのでクラスをインスタンス化せずにクラス名の後にTalk()を記述して呼び出せます。

クラスをインスタンス化(実体化)するには

クラス名 変数名 = new クラス名();

と記述します。

インスタンス化したクラスを参照するのがlearn変数なのでlearnを通してRunメソッドを呼び出します。

Learn1_2クラスにstatic修飾子を取りつけた場合

↑のようになりますが、静的なクラスはインスタンス化する事が出来なくなります。

また静的なクラスの場合はメソッド等は全てstaticがついた静的なメンバーである必要があります。

フィールド定義

メソッドに続きフィールドも定義してみます。

Learn1_3クラスを作成します。

↑のようにフィールドをprivate修飾子を付けて型と変数名を付けて宣言してます。

フィールドはクラス全体で参照出来る変数といった感じです。

アクセス修飾子にprivateを設定しているのでこのクラスからしかアクセス出来ないので外部のクラスからフィールドの値を設定したり、フィールドの値を参照したりが出来るようにSetterとGetterを用意しています。

SetTalkを見ると引数として文字列型(string)のtalk変数に呼び出し元から渡された値が入ります。

値の渡し方は値型と参照型で異なりますが今回はスルーしていきます。

引数の変数名をtalkとしたことで、フィールド名のtalkと名前がかぶってしまいました。

そこでthis.talkと記述することでこのクラスのフィールドであるtalkを指定しています。

もしここを

talk = talk;

としてしまうと引数として受け取ったtalkを引数のtalkに入れるだけでフィールドの操作はまったく行われません。

それではLearn1_3クラスをインスタンス化しフィールドの操作をしてみましょう。

Learn1_3クラスをインスタンス化しそれぞれのフィールドにSetterで値を設定した後、Getterで値を取得しUnityのコンソールに表示しています。

上記のスクリプトを実行すると

テスト
10
5.5

と表示されます。

SetterとGetterをフィールド毎に設定していますが、この面倒臭い記述を無くしてプロパティを使ってアクセスする事も出来ます。

それは後でやります。

フィールドの初期化を行うコンストラクタ

クラスをインスタンス化した時にフィールドの初期化等をしたい事があります。

そんな時に使用するのがコンストラクタです。

コンストラクタはクラス名にアクセス修飾子を付けただけのものを書きます。

コンストラクタを定義していなければデフォルトコンストラクタが呼ばれます。

コンストラクタが4つ宣言されています。

コンストラクタやメソッドは引数の型や数の違いによって同名でも引数に応じたものを呼び出すオーバーロードという機能が利用出来ます。

フィールドの値を初期化したいけど全部の引数を指定しなくてもいい場合は1つの引数だけを指定して呼び出したりします。

4つのコンストラクタそれぞれでフィールドの初期化処理のコードを書くのは大変なので: thisを使って自身の他のコンストラクタを呼び出しています。

例えば引数に何も設定しないでインスタンス化した場合は

のコンストラクタが実行されますが、: thisを使って同じコンストラクタの引数が3つのものを呼び出しています。

こうすると引数に何も設定されていないでインスタンス化されたオブジェクトのフィールドに既定値を設定する事が出来ます。

実行順序はLearn1_4()の中身を実行した後に引数付きのコンストラクタを実行します。

フィールドの初期化をもっと簡単に

: thisを使うと引数によって呼び出すコンストラクタを変更すればいいことはわかりましたが、これでも同じような記述が増えますね。

それをもっと簡単にすると

コンストラクタを引数の個数毎に作成せず、あらかじめ空であれば設定する値を入れておくだけで大丈夫なようです。

このクラスをインスタンス化し実行してみましょう。

Startメソッド内でLearn1_5クラスをインスタンス化しゲッターを呼んでフィールドの値を表示しています。

実行すると

テスト
10
5.5

がUnityのコンソールに表示されます。

フィールドのSetterとGetterを簡単にする

フィールドに値を設定したり取得したりといった事はSetterとGetterメソッドを作成しそれぞれにアクセスしていました。

ですがフィールドが多くなってくるとそれぞれにアクセスするメソッドを定義するだけで大変ですし、プログラムのコード量が増えてしまいますね。

そこでフィールドをプロパティを自動実装する記述に変更しSetterとGetterの記述をなくします。

プロパティ名の最初は大文字にするみたいです。

Learn1_5をプロパティの記述に変えてLearn1_6クラスとします。

↑のようにアクセス修飾子をpublicにしプロパティ名を記述し、get、setを書きます。

プロパティに値を設定するのはコンストラクタのみで指定する場合はprivate修飾子を付け外部スクリプトから操作出来ないようにします。

実際にLearn1_6クラスをインスタンス化して使ってみます。

Learn1_6クラスを作成し、プロパティの値をコンソールに表示してます。

learn.Talk = “書き換え文字列”;

ではプロパティをprivateに設定している為、エラーになります。

値を書き換える為にはプロパティのアクセス修飾子privateを消します。

実行すると

テスト
10
5.5

と表示されます。

プロパティをフィールドのアクセサーとして使う

次にフィールドの操作をプロパティから行うようにしてみます。

まずはLearn1_8クラスを作成します。

フィールドをprivateにし、プロパティをpublicにしてget、setのアクセス制限のprivateを外し、プロパティを介してフィールド値を操作出来るようにします。

プロパティを介する事で値のチェック等もする事が出来ます。

プロパティのsetのprivateを外した事で、Learn1_8クラスをインスタンス化し使用する時にオブジェクト初期化子を使って、プロパティ値を設定する事が出来ます。

終わりに

わたくしがC#の勉強に使っている本は

です。

プログラミングの基礎を勉強した人向けですが、プログラミングの定石について学習する事が出来ます。

JavaやJavaScriptを多少勉強したことはあるんですが、C#は今回が初めてです。

C#はJavaとも多少違いますね。

現状のJavaがどうなっているかはわかりませんが・・・・(^_^;)

今回はとりあえずクラスの定義といった基本的な事を学習しました。

んー・・・全然ゆるい感じのカテゴリになってない・・・・。

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます