class Base
{
}
class Sub : Base
{
}
class Base
{
public void Method1() { }
public virtual void Method2() { }
public virtual void Method3() { }
}
class Sub : Base
{
public void Method1() { } // CS0108 'Sub.Method1()' は継承されたメンバー 'Base.Method1()' を非表示にします。非表示にする場合は、キーワード new を使用してください。
public void Method2() { } // CS0114 'Sub.Method2()' は継承されたメンバー 'Base.Method2()' を非表示にします。現在のメンバーでその実装をオーバーライドするには、override キーワードを追加してください。オーバーライドしない場合は、new キーワードを追加してください。
public override void Method3() { } // OK
}
class Base1
{
public abstract void Method1(); // CS0513 'Base1.Method1()' は抽象ですが、非抽象クラスの 'Base1' に含まれています。
}
abstract class Base2
{
public abstract void Method1() { } // CS0500 'Base2.Method1()' は abstract に指定されているため本体を宣言できません。
public abstract void Method2(); // OK
}
class Sub : Base2 // CS0534 'Sub' は継承抽象メンバー 'Base2.Method1()' を実装しません。
{
public void Method1() { } // CS0114 'Sub.Method1()' は継承されたメンバー 'Base2.Method1()' を非表示にします。現在のメンバーでその実装をオーバーライドするには、override キーワードを追加してください。オーバーライドしない場合は、new キーワードを追加してください。
public override void Method2() { } // OK
}
virtualやabstractで宣言されているメンバを、拡張して実装します。
abstract class Base1
{
public void Method1() { }
public virtual void Method2() { }
public abstract void Method3();
}
class Sub : Base1
{
public override void Method0() { } // CS0115 'Sub.Method0()': オーバーライドする適切なメソッドが見つかりませんでした。
public override void Method1() { } // CS0506 'Sub.Method1()': 継承されたメンバー 'Base1.Method1()' は virtual、abstract または override に設定されていないためオーバーライドできません。
public override void Method2() { } // OK
public override void Method3() { } // OK
}
派生クラス (derived class) から、オーバーライドした基本クラス (base class / 基底クラス) のメンバを呼び出せます。base キーワード - C# リファレンス | Microsoft Learn
public override void Method2()
{
base.Method2();
}
class Base1
{
protected virtual void Method1() { }
protected virtual void Method2() { }
protected virtual void Method3() { }
protected virtual void Method4() { }
}
class Sub : Base1
{
public override void Method1() { } // CS0507 'Sub.Method1()': 'protected' の継承メンバー 'Base1.Method1()' をオーバーライドするときに、アクセス修飾子を変更できません。
public new void Method2() { } // OK
protected override void Method3() { } // OK
protected new void Method4() { } // OK
}
派生クラスでnewで非表示にしたメンバの、アクセス修飾子を変更する場合を考えます。
class Base1
{
public void Method1() { Console.Write("Base"); }
public void Method2() { Console.Write("Base"); }
private void Method3() { Console.Write("Base"); }
private void Method4() { Console.Write("Base"); }
}
class Sub : Base1
{
public new void Method1() { Console.Write("Sub"); }
private new void Method2() { Console.Write("Sub"); }
public new void Method3() { Console.Write("Sub"); } // warning CS0109: メンバー 'Sub.Method3()' は継承されたメンバーを非表示にしません。new キーワードは不要です。
private new void Method4() { Console.Write("Sub"); } // warning CS0109: メンバー 'Sub.Method4()' は継承されたメンバーを非表示にしません。new キーワードは不要です。
public void Func()
{
Method1(); // Sub
Method2(); // Sub … 派生クラスのメンバへアクセス可能なため、それが呼ばれる
Method3(); // Sub
Method4(); // Sub
}
}
派生クラスのインスタンスから呼ぶ場合は、アクセス可能なメンバが呼ばれます。
Sub sub = new Sub(); sub.Method1(); // Sub sub.Method2(); // Base … 派生クラスのメンバはprivateなため、基本クラスのそれが呼ばれる sub.Method3(); // Sub sub.Method4(); // error CS0122: 'Sub.Method4()' はアクセスできない保護レベルになっています
基本クラスと、それを継承した派生クラスを定義して検証します。
class Base
{
public virtual void Method1() { Console.Write("Base"); }
public virtual void Method2() { Console.Write("Base"); }
}
class Sub : Base
{
public override void Method1() { Console.Write("Sub"); }
public new void Method2() { Console.Write("Sub"); }
}
次の3通りの場合について、それぞれ呼ばれるメソッドを確認します。
// 1 Base c1 = new Base(); c1.Method1(); // Base … 基本クラスのメソッドが呼ばれる c1.Method2(); // Base … 同上 // 2 Sub c2 = new Sub(); c2.Method1(); // Sub … 派生クラスのメソッドが呼ばれる c2.Method2(); // Sub … 同上 // 3 Base c3 = new Sub(); c3.Method1(); // Sub … overrideで拡張されていると、派生クラスのメソッドが呼ばれる c3.Method2(); // Base … newで隠蔽されていると、基本クラスのメソッドが呼ばれる
class C1
{
public virtual void M1() { Console.Write("C1"); }
public virtual void M2() { Console.Write("C1"); }
public virtual void M3() { Console.Write("C1"); }
}
class C2 : C1
{
public override void M1() { Console.Write("C2"); }
public override void M2() { Console.Write("C2"); }
public new void M3() { Console.Write("C2"); }
}
class C3 : C2
{
public override void M1() { Console.Write("C3"); }
public new void M2() { Console.Write("C3"); }
public new void M3() { Console.Write("C3"); }
}
C3 c3 = new C3(); ((C1)c3).M1(); // C3 ((C1)c3).M2(); // C2 ((C1)c3).M3(); // C1 … C2.M3()がnewで隠蔽されているため ((C2)c3).M1(); // C3 ((C2)c3).M2(); // C2 … C3.M2()がnewで隠蔽されているため ((C2)c3).M3(); // C2 … C3.M3()がnewで隠蔽されているため c3.M1(); // C3 c3.M2(); // C3 c3.M3(); // C3
newで隠蔽されていると、呼び出し元の型のメソッドが呼ばれます。
コントロールを継承したときには、ビュー デザイナーで意図せずコードが追加されないように、必要ならばDesignerSerializationVisibilityAttribute属性を設定します。