継承 -newとbase-

ホームC#プログラミング応用講義 > newとbase

目次

名前の衝突

名前の衝突
名前が衝突するというのはどういうことか、それを説明します。

衝突

衝突というのは、同じ名前のメンバがあって、混乱してしまうことです。
図のように「変数 A」が基本クラスにも派生クラスにもあると、派生クラスでは基本クラスのメンバを自由に扱えますから、名前の衝突が起こってしまいます。

衝突は簡単に理解できても、実際に使うときには苦労する場合が多いものです。
もし衝突を回避できなければ重大なエラーが発生することになってしまいます。

C# の言語仕様は全体として「危なさそう」なものはすべて厳格に処理するようになっており、一切あいまいさを残していません。
その一例は厳格な「型」であり、そしてまたこの「名前の衝突」でもあります。

とはいってもやはり同じ名前を使いたいときはあるでしょう。そのために用意されたキーワードがあります。
基本クラスと同じ名前の派生クラスのメンバには、宣言の際に「new」キーワードをつけます
そして、やっぱり基本クラスのメンバにアクセスしたくなったら「base」キーワードに続けてアクセスします。まるで this のように。

では、それぞれのキーワードに関して解説していきましょう。

新しいnew

「new とは何ですか。説明しなさい。」
という問題が出たら、
クラスからオブジェクトを生成する際に利用するキーワードの一種
と答えて間違いはありません。

ここでご紹介する new は全く新しい new であり、上に述べた用途とは全く違います。
しかし、利用する頻度ははるかに上で述べた用途のほうが多いので、あの解答が正解になります。皆さんも「新しい new」と考えておいてください。

基本クラスに dorama という名前の変数があり、派生クラスでも dorama を宣言したいときにこのキーワードを使います。
dorama は再利用するのではなく、全く別のものであることをあらかじめ述べておきます。(次の項目で確認できます)
using System;

class BaseClass
{
    public string dorama = "夏クール「東京湾景」に注目";
}

class Dorama : BaseClass
{
    new string dorama = "仲間由紀恵主演!!";
    
    public static void Main(string[] args)
    {
        Dorama d = new Dorama();
        d.Show();
    }
    
    private void Show()
    {
        Console.WriteLine(dorama);
    }
}
BaseClass には dorama という変数が宣言されています。ここでは当然 public ですね。
それはさておき、ソースを見て、なかなか分からないときは「Main()」から見るようにするとわかるものです。

Main() では自分のクラスからオブジェクトを生成しています。で、Show() メソッドを呼び出していることがわかります。

Show() メソッドを探して見ると、dorama という変数があるのに気づきます。
上のほうに目を動かすと確かに
new string dorama = "仲間由紀恵主演!!";
がありますから、これが表示されるのがわかります。

そしてその予想通り、基本クラスにも dorama があるにもかかわらず「仲間由紀恵主演!!」が表示されます。
それはすべて「new」があるからです。

話が変わりますが、Windows のゴミ箱を思い浮かべてください。
同じフォルダに同じ名前のファイルは作れませんから、片一方をゴミ箱に捨てます。

new をつけると new がないものがゴミ箱に捨てられ、new が付いているものが生き残ります。
よって、単に「dorama」とアクセスすると生き残った dorama が呼び出されます。

もう1度言いますが、
new Dorama()
の new とは別物であると理解してください。

ちなみに、ゴミ箱に捨てたものは元に戻せますよね。しかもそのままの形で。
ゴミ箱の中には捨てられたふりをしている基本クラスの dorama が生き残っているのです。

base

ゴミ箱に捨てたものはゴミ箱の中ながらも生き残っています。
その「ゴミ箱」に対してアクセスするのが base キーワードです。

this キーワードは自分が今表示しているフォルダにアクセスするようなもので、多くの場合つけてもつけなくてもかまいません。
ただ、this はインスタンス(実体)が入っていますから、static メンバには付けてはいけません。

それに対して base はゴミ箱という特殊な場所を示します。よって、ゴミ箱の中をあさる際は必ずつけます。
ここで言うゴミ箱とは「基本クラス」にあたります。
using System;

class BaseClass
{
    public string dorama = "夏クール「東京湾景」に注目";
}

class Dorama : BaseClass
{
    new string dorama = "仲間由紀恵主演!!";
    
    public static void Main(string[] args)
    {
        Dorama d = new Dorama();
        d.Show();
    }
    
    private void Show()
    {
        Console.WriteLine(dorama);
        Console.WriteLine(base.dorama);
    }
}
さっきと違うのは
Console.WriteLine(base.dorama);
の部分だけです。これを追加した形になります。

派生クラス Dorama で new をつけて dorama を宣言した段階で、基本クラスの dorama はゴミ箱へいきます。
そのゴミ箱の中の dorama にアクセスしているステートメントです。

何度も言いますが、dorama には「"夏クール「東京湾景」に注目"」が入っていますから、それはゴミ箱の中で生きたままなのでこれが表示されます。
しかし、base なしでは Dorama から BaseClass.dorama にアクセスすることはできません。

よって、余りに頻繁に利用するのは避けたほうがいいでしょう。どれもこれも new をつける必要があるならば、基本クラスに宣言した変数を再考慮すべきです。
new/base を利用するほうが簡潔でよりよいと判断されるときには大いに利用しましょう。

ちなみに new/base はセットで利用するものではありません。new を使ったとしても base を使わないことはしばしばあります。
しかし、base を使って new を使わないときはまずありません。その際は名前の衝突が発生していない、すなわち同名の変数が複数存在しないということになりますから、前単元でやったように何もつけずにアクセスします。

[ ステップアップC# ] [ C#プログラミング応用講義 ]