この章のテーマ §
abstractキーワードとinterfaceキーワードについて学びます。
前提知識 §
Console.WriteLineメソッド, 文字列の基礎, 変数の基礎, クラスの基礎, 継承の基礎
解説 §
C#には、抽象メソッドなどの抽象メンバー、抽象クラスというものがあります。これらは、メソッドやクラスにabstractキーワードを付けて実現します。抽象メソッドは実行する文が無く、宣言だけ存在するメソッドです。これは、継承時に中味を入れない限り呼び出せません。しかし、呼び出すコードは記述できます。抽象クラスは抽象メンバーで構成されたクラスです。
これらは共通の呼び出し規約で複数の機能を提供するのに便利なので用意されています。
似て非なる機能に、インターフェース(interface)があります。インターフェースも実行する文を持たないメンバーを並べて、継承と同じような方法で実行する文を実装して使います。インターフェースの実装には通常の実装と明示的な実装があります。明示的な実装は、型名+"."+メンバー名という名前で定義され、そのインターフェースの型を経由してアクセスした時のみ呼び出せます。サンプルソースでは、キャストして呼び出しています。名前の衝突が起きたときに便利な機能です。
抽象クラスとインターフェースの違いは多くあります。
- インターフェースはclassではなくinterfaceキーワードを使う
- インターフェースは実装する際にoverrideキーワードを必要としない
- 継承は1つのクラスからしかできないが、インターフェースはいくつでも実装できる
- インターフェースのメンバーにアクセス修飾子は要らない (アクセスの制限を付けても実装できなくなるだけで意味がない)
罠の数々 §
- 多重継承といって、複数のクラスから継承できる機能を持ったプログラミング言語もあるが、C# は1つのクラスからのみ継承できるスタイルのプログラミング言語の一つである。複数の定義を取り入れたいときはインターフェースを使って対処する
- クラスもインターフェースも、抽象メンバーと実装のあるメンバーを記述できるが、細部の制約は異なるので注意が必要である
参考リンク §
abstract (C# リファレンス)
interface (C# リファレンス)
サンプルソース: kw_abstract_interface §
var x1 = new SampleB();
x1.sub();
var x2 = new SampleD();
x2.sub();
var x3 = new SampleE();
((ISampleC)x3).sub();
abstract class SampleA
{
public abstract void sub();
}
// 抽象クラスの実装
class SampleB : SampleA
{
public override void sub() => Console.WriteLine("I'm ClassB.A");
}
interface ISampleC
{
void sub();
}
// インターフェースの実装
class SampleD : ISampleC
{
public void sub() => Console.WriteLine("I'm ClassD.A");
}
// インターフェースの明示的な実装
class SampleE : ISampleC
{
void ISampleC.sub() => Console.WriteLine("I'm ClassE.A");
}
実行結果 §
I'm ClassB.A
I'm ClassD.A
I'm ClassE.A
リポジトリ §
https://github.com/autumn009/CSharpPrimer2
練習問題 §
以下のクラスはあり? なし? なしなら原因は何?
public abstract class MyClass
{
public abstract void sub1();
public void sub2()
{
sub1();
}
}
- あり。
- なし。実装のないsub1を呼ぶコードを含んでいるから。
- なし。抽象クラスはインスタンス化できないから永遠に利用できない。
[[解答]]