C#はC++とJavaを源流とする言語なんだそうです。ということは、オブジェクト指向であり、クラスという概念を避けて通れません。特にC#では、前回のエントリーにも書いたように、全ての手続きはクラスに属さなければならない決まりになっているので、プログラムを書く=クラスを定義する、ということになります。マイクロソフトのこのドキュメントの二つ目のパラグラフに書いてありますね。
クラス
次のリストは、私がクラスの定義の学習をしたときに使ったプログラムです。
using System; namespace sample5 { class Program { static void Main(string[] args) { MyObject obj = new MyObject(); obj.name = "Gustav"; obj.age = 56; obj.printData(); Console.ReadKey(); } } class MyObject { public string name = "(noname)"; public int age = 0; public void printData() { Console.WriteLine("名前 : {0}, 年齢 : {1}歳",name, age); } } }この中では、sample5という名前空間(クラスを整理する為の棚のようなもの)の中に、ProgramというクラスとMyObjectというクラスが定義されています。ProgramクラスにはMainメソッドがありますね。OS上の各種セットアップ処理が終わった後に、プログラム本体の入口としてここに制御が移ります。
下にあるMyObjectクラスの定義では、メンバーの変数やメソッドの定義がなされます。ここで、各メンバーにはpublic宣言がなされているので、MyObjectクラスの外からこれらメンバーを読んだり書いたり呼び出したりできますが、private宣言というものもあり、private宣言がなされたメンバーは、クラスの外からはアクセスできません。
Mainメソッドの1行目で、
MyObject obj = new MyObject();
という記述がされています。
実は、C#ではstatic宣言がされているクラスを除いて、クラスはnew演算子を使って実態を作る(インスタンスを作る)操作をしないと、使うことが出来ません。クラスの宣言は文字通り宣言だけで、実態を作ることで初めて使うことができる、ということになっています。
C++では、new演算子を使うインスタンス生成と使わないインスタンス生成がありますが、C#では、クラスのインスタンス生成には必ずnew演算子を使う決まりになっています。
なお、C++におけるインスタンス生成で、new 演算子を使った場合はオブジェクトがヒープ領域に、使わない場合はスタック領域に生成され、new演算を使わない場合は、スコープから抜けるとオブジェクトは開放されてしまいます。
クラスの継承
この概念、個人で小規模なプログラミングをやってる人間にはあまりありがたみが分からないのですが、チームで仕様書ベースで開発するようなケースでは有用なのでしょう。また、あらかじめ用意されている、たとえば.NETの環境で、ライブラリーを継承して新たにクラスを作る、なんてときには嬉しい機能なのだと今回の学習で思いました。
なお、継承元のクラスを基底クラス、又はスーパークラス、継承を受ける側を派生クラス、又はサブクラスと呼びます。
次のリストでは、クラスの継承をしています。MyObjectクラスの定義があり、その次にEnchancedMyObjectクラスの定義がありますが、
class EnhancedMyObject : MyObject
の、": MyObject"の記述が、MyObjectクラスを継承することを示しています。
using System; namespace sample6 { class Program { static void Main(string[] args) { EnhancedMyObject obj = new EnhancedMyObject(); obj.name = "Gustav"; obj.age = 56; obj.mail = "mail@truth-maker.com"; obj.printData(); obj.printDataEnchanced(); Console.ReadKey(); } } class MyObject { public string name = "(noname)"; public int age = 0; public void printData() { Console.WriteLine("名前 : {0}, 年齢 : {1}歳",name, age); } } class EnhancedMyObject : MyObject { public string mail = "(no mail)"; public void printDataEnchanced() { Console.WriteLine("名前 : {0}\n\t 年齢 : {1}歳\n\t メール : {2}.", name, age, mail ); } } }
Mainメソッドの中で、EnhancedMyObject型のオブジェクトをnew演算子で生成しています。そして、obj.printData()メソッドとobj.printDataEnhanced()メソッドを呼び出しています。
obj.printData()メソッドは、基底クラスに存在しているメソッドなので、派生クラスにも引き継がれ、派生クラスでも使うことが出来ます。プログラムを実行すると、下記のような結果になります。
1行目でソースのコンパイル、2行目で実行させています。
MacBook-Pro:sample6 gustav$ mcs Program.cs MacBook-Pro:sample6 gustav$ mono Program.exe 名前 : Gustav, 年齢 : 56歳 名前 : Gustav 年齢 : 56歳 メール : mail@truth-maker.com.
まず最初に基底クラスから引き継がれたのprintData()メソッドが実行され、次に派生クラスで追加したprintDataEnhanced()メソッドが実行されていますね。
今回はクラスと継承のお話でした。今回はここまで。
通常、public変数は使用しない方がよいと思いますが…
返信削除コメントありがとうございます。ご教授ありがとうございます。
削除他のクラスから参照できなくても構わない変数は、privateもしくはprotected指定をすべきと認識しています。継承されることを考えるとprotectedが妥当でしょうか。
しかし、他のクラスから参照できないと困るような変数があるときだけ、該当する変数をpublicにするのは許されると思っています。
ありがとうございました。
ご丁寧な返信で嬉しかったので、もう少し書きますね。
返信削除public変数にしてしまうと、何時でも内部の値を変更できてしまう状態なのでカプセル化されていないことを意味します。
なので、private一択という認識です。
また、継承もですがこれも使わない方がよいかと…
使いどころが難しいので、私は使用しないようにしています。
参考になれば嬉しいです。
ありがとうございます。参考にさせていただきます。
削除今後ともよろしくお願いいたします。