ポリモーフィズム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { // 変数の型: 静的な型 // インスタンスの型: 動的な型 Base a = new Base(); Base b = new derived(); // 基底クラスの型に派生クラスを格納できる。 // derived c = new Base(); これはエラー derived d = new derived(); // typeof() は静的な型を取得できる。 Console.WriteLine(typeof(Base)); // GetType() は動的な型を取得できる。 Console.WriteLine(b.GetType()); // #=> derived /* 基底クラスの変数に派生クラスの変数を渡すこと:アップキャスト 派生クラスの変数に基底クラスの変数を渡すこと: ダウンキャスト ダウンキャストは明示的なキャストが必要 */ //-------------------------------------------------------- // 静的な型を優先してメソッドは呼ばれる。 a.jump(); // this is base b.jump(); // this is base d.jump(); // this is derived // bはアップキャストされている。 // a.RayDown(); ここはエラー。 // b.RayDown(); ここはエラー。 d.RayDown(); /* bは派生クラス(derived)の変数が格納されているが、 derivedに定義されているRayDown()は呼べない つまり呼べるメソッドは変数の型(静的な型)によって決まる。*/ // virtual,overrideを付けると動的な型でメソッドを呼べる。 Console.ReadKey(); } } class Base { internal void jump() { Console.WriteLine("this is base"); } } class derived: Base { // jumpはoverrideされている。 internal void jump() { Console.WriteLine("this is derived"); } internal void RayDown() { Console.WriteLine("Ray Down"); } } } |
アップキャストは問題ない。ダウンキャストは明示キャストが必要。
ダウンキャストの変換はキャスト元の変数が保持しているインスタンスがキャスト先のクラスと同じの必要がある。通常、アップキャストして戻すときにダウンキャストが発生する。
virtual-overrideがなくても基底クラスでの定義されたメソッドは派生クラスで上書(隠蔽)きできる。ただコンパイラが警告は出す。その状態だと変数の型で呼び出されるメソッドが決まる。virtualだけ付けてoverrideを付けないと同じく変数の型で呼び出す。virtual-overrideがついてインスタンスの型で呼び出す。派生クラスでoverrideだけ付けてvirtualがないとコンパイルエラーになる。
virtual-overrideされるとインスタンスの型で呼ばれるメソッドが決まる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { // アップキャスト: 基底クラスの変数に派生クラスのインスタンスを格納 // ダウンキャスト: 派生クラスの変数に基底クラスのインスタンスを格納 Base a = new Base(); Base b = new derived(); // アップキャスト // -------------------------------------------------------- // 以下ダウンキャスト // derived c = (derived)new Base(); これはキャストエラー。 /* Base tmp = new Base(); derived c = new derived(); c = (derived)tmp; これはキャストエラー。 */ derived c = new Base() as derived; // キャストエラーにはならないけど、cはnullになっている。 /* ダウンキャストの変換はキャスト元の変数が 保持しているインスタンスがキャスト先のクラスと同じの必要がある。 通常、アップキャストして戻すときにダウンキャストが発生する。 */ derived d = new derived(); // -------------------------------------------------------- // メソッド呼び出し a.jump(); // this is base b.jump(); // this is derived //c.jump(); d.jump(); // this is derived /* virtula-overrideを付けると、インスタンスの型で 呼び出すメソッドが決まる。 virtual-overrideが無いとbはbaseとなるが、今回は インスタンスの型なので、derivedとなる。 */ Console.ReadKey(); } } class Base { public virtual void jump() { Console.WriteLine("this is base"); } } class derived: Base { public override void jump() { Console.WriteLine("this is derived"); } } } |
メソッドのシグネチャ
メソッド名、パラメータの数、順序、型
CLRでは戻り値の型をシグネチャに含めているのでC#/VBとは違う。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
string sample() { return ""; } int sample() //同じパラメータの型で既に定義しています。 { return 0; } string sample1(string tmp) { return ""; } string sample1(int tmp) { return ""; } |