スポンサーリンク
※サイト運営にサーバーは必須です※
~このサイトもエックスサーバーを使用しています~
目次
newキーワード
基本クラスのメンバと派生クラスのメンバで同じ名前を使用することは可能です。
※メンバとは、フィールド、プロパティ、メソッドなど、クラスの構成要素を意味します。
基本クラスのメンバと同じ名前を使用したい場合、派生クラスのメンバに対してnewキーワードを付けます。
派生クラスのメンバにnewキーワードを付けることで、外部からアクセスがあった場合に派生クラスのメンバが採用されるようになります。
このように、基本クラスのメンバを派生クラスによって隠すことを「名前の隠蔽」と呼びます。
※「名前の隠蔽」のために使用するnewキーワードは、クラスをインスタンス化する際に使用するnew演算子とは別物です。
※実は、newキーワードを付けなくても、警告は出ますがエラーにはなりません。そのため、newキーワードを省いたとしても、ビルドエラーにはなりません。ただし、ソースコードのリーダビリティという観点で考えると、newキーワードは必ず付けるべきでしょう。
ソースコード
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 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace New03 { class Base { public int _num = 100; } class Derived : Base { new public int _num = 200; } class Program { static void Main(string[] args) { Derived de = new Derived(); Console.WriteLine(de._num); } } } |
実行結果
200
このように、基本クラス(Baseクラス)の_numではなく、派生クラス(Derivedクラス)の_numが呼び出されます。
※フィールドを例に挙げましたが、メソッドでもnewキーワードは使用可能です。
baseキーワード
基本クラスのメンバの名前を隠蔽したいが、呼び出したいという場合は、baseキーワードを使用します。
baseキーワードを使用することで、派生クラスから基本クラスの隠蔽されたメンバにアクセスできます。
ソースコード
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 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace New04 { class Base { public int _num = 100; } class Derived : Base { new public int _num = 200; public void ShowDerivedNum() { Console.WriteLine("派生クラスの値を呼び出します"); Console.WriteLine(_num); } public void ShowBaseNum() { Console.WriteLine("基本クラスの値を呼び出します"); Console.WriteLine(base._num); } } class Program { static void Main(string[] args) { Derived de = new Derived(); de.ShowDerivedNum(); de.ShowBaseNum(); } } } |
実行結果
派生クラスの値を呼び出します
200
基本クラスの値を呼び出します
100
特殊なケース
基本クラス(Firstクラス)から派生クラス(Secondクラス)を作り、さらに、派生クラス(Secondクラス)を継承した派生クラス(Thirdクラス)を作成したとします。
この時、派生クラス(Thirdクラス)でbaseキーワードを使用した場合、FirstクラスとSecondクラスのうちどちらが優先して呼び出されるでしょうか?
ソースコード
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 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace New05 { class First { public int _num = 100; } class Second : First { new public int _num = 200; } class Third : Second { new public int _num = 300; public void ShowBaseNum() { Console.WriteLine("base._numの値を呼び出します"); Console.WriteLine(base._num); } } class Program { static void Main(string[] args) { Third th = new Third(); th.ShowBaseNum(); } } } |
実行結果
base._numの値を呼び出します
200
FirstクラスよりSecondクラスの方が優先して呼び出されます。
※Firstクラスの._numの値をアクセスしたいからといって、base.base.~みたいな書き方はできません。
注意点(使用可能なパターン)
baseキーワードによって基本クラスにアクセスできるのは以下の3パターンです。
・コンストラクター
・インスタンスメソッド
・インスタンスプロパティのアクセサー
逆に言えば、以下のような場合はbaseキーワードを使用できません
・派生クラスでないクラスからのアクセス
・フィールド(メンバ変数)
・静的メソッド
・静的プロパティ
アクセスできるパターンのみ集めたソースコード
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 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace New06 { class Base { public int _num; } class Derived : Base { new public int _num; //コンストラクター public Derived(int i) { base._num = i; Console.WriteLine("コンストラクターが呼び出されました"); Console.WriteLine(base._num); } //インスタンスメソッド public void ShowBaseNum() { Console.WriteLine("インスタンスメソッドが呼び出されました"); Console.WriteLine(base._num); } //インスタンスプロパティ public int BaseNum { get { return base._num; } set { base._num = value; } } } class Program { static void Main(string[] args) { Derived de = new Derived(10); de.ShowBaseNum(); de.BaseNum = 30; de.ShowBaseNum(); } } } |
実行結果
コンストラクターが呼び出されました
10
インスタンスメソッドが呼び出されました
10
インスタンスメソッドが呼び出されました
30
アクセスできないパターンのみ集めたソースコード
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 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace New07 { class Base { public int _num = 100; } class Derived : Base { new public int _num = 200; //フィールド new public int _baseNum = base._num; //静的メソッド static public void ShowBaseNum() { Console.WriteLine("インスタンスメソッドが呼び出されました"); Console.WriteLine(base._num); } //静的プロパティ static public int BaseNum { get { return base._num; } set { base._num = value; } } } class Program { static void Main(string[] args) { Derived de = new Derived(); //派生クラスでないクラスからのアクセス Console.WriteLine(de.base._num); } } } |
※エラーになります
~プログラミングを勉強してみませんか?~
TechAcademy [テックアカデミー] は無料の体験講座が用意されているので、気軽に体験できます。
※私(サイト主)も無料体験講座を実際に受けてみました(→感想)