.NET開発者のためのブログメディア

C#のabstract classとは?インターフェイスについても併せて解説!
- SE
- C#のabstractclassはとても難しいですね。
- PM
- そうかもしれませんが、C#のabstractclassを知ると、オブジェクト指向についての理解も深まりますよ。
目次
C#のabstract classとは?
C#のabstract classは抽象クラスを宣言するためのキーワードです。抽象クラスには以下のような特徴があります。
1.抽象クラスはインスタンス化できない(newできない)
2.抽象クラスは抽象メソッドや抽象アクセサを記述できる
3.abstract classとsealedは矛盾するため併用できない
4.抽象クラスから派生した普通のクラスは、全ての抽象メソッドとアクセサを、オーバーライドして実装する必要がある
abstract classの特徴
上のabstract classの4つの特徴を実例で説明しましょう。以下のC#のサンプルをご覧ください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
sealed abstract class Animal
{
public abstract void Walk();
}
class Dog : Animal
{
}
public static void Main()
{
Animal a = new Animal();
}
|
abstract classの制約
上のC#サンプルは複数のエラーが出ます。まずMainメソッドの「Animal a = new Animal();」でAnimalのインスタンスを生成できないというエラーになります。また「sealed abstract class Animal」で、抽象クラスには派生を禁じるsealedは使用できないというエラーになります。
またsealedを消しても、「class Dog : Animal」で継承抽象メンバーのWalk()を実装していないというエラーになります。
修正版のサンプル
上のエラーを解消したC#サンプルが以下になります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
abstract class Animal
{
public abstract void Walk();
}
class Dog : Animal
{
public override void Walk()
{
Console.WriteLine(“犬が歩く。”);
}
}
public static void Main()
{
Animal a = new Dog();
a.Walk();
}
|
実行結果は以下になります。
犬が歩く。
抽象メソッドについて
上のC#サンプルのAnimalには「public abstract void Walk()」という空のメソッドがあります。これを抽象メソッドと言います。抽象メソッドは抽象クラスのみに実装できるので、クラスの宣言にabstractが無いとエラーになります。
抽象クラスを拡張したクラスでは、抽象クラスの抽象メソッドをoverrideを付けて同名で実装することが強制されます。この仕様は何のためにあるのでしょうか。
抽象メソッドの用途
抽象メソッドは以下のC#サンプルのようなことを実現するためにあります。
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
|
abstract class Animal
{
public abstract void Walk();
}
class Dog : Animal
{
public override void Walk()
{
Console.WriteLine(“犬が歩く。”);
}
}
class Cat : Animal
{
public override void Walk()
{
Console.WriteLine(“猫が歩く。”);
}
}
public static void Main()
{
var l = new List<Animal>();
l.Add(new Dog());
l.Add(new Cat());
foreach(Animal a in l)
{
a.Walk();
}
}
|
抽象メソッドによりポリモーフィズムを実現できる
上のC#サンプルには抽象クラスのAnimalを拡張したDogクラスとCatクラスがあります。MainメソッドでAnimal型のListを宣言し、それにDogとCatを生成して追加しています。DogとCatの親クラスがAnimalのためこれが可能になります。
そしてforeachループでListの中のインスタンスのWalkメソッドを呼び出しています。Walkメソッドの実装が強制されているからこれが可能になるのです。このようなやり方は「ポリモーフィズム」と呼ばれ、オブジェクト指向の重要な要素となっています。
実行結果は以下になります。
犬が歩く。
猫が歩く。
インターフェイスについて
C#には抽象クラスに似た機能でインターフェイスがあります。上のサンプルのAnimal、Dog、Catを以下のように変更しても、全く同じように動作します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
interface Animal
{
public void Walk();
}
class Dog : Animal
{
public void Walk()
{
Console.WriteLine(“犬が歩く。”);
}
}
class Cat : Animal
{
public void Walk()
{
Console.WriteLine(“猫が歩く。”);
}
}
|
インターフェイスのメリット
抽象クラスとインターフェイスはどう使い分ければよいのでしょうか。それをするにはまず、それぞれの違いを知ることが必要です。インターフェイスにあって抽象クラスに無い機能については、インターフェイスは以下のように複数を実装することができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
interface Animal
{
public void Walk();
}
interface Wing
{
public void Fly();
}
class Bat : Animal,Wing
{
public void Walk()
{
Console.WriteLine(“コウモリが歩く。”);
}
public void Fly()
{
Console.WriteLine(“コウモリが飛ぶ。”);
}
}
|
インターフェイスにかつてあった制約
C#は多重継承ができないため、複数の抽象クラスを親に持つことはできません。そうであれば、常に抽象クラスよりインターフェイスを使った方が良いのでしょうか。しかしインターフェイスには抽象クラスと比べて、C# 8.0以前では以下のような制約がありました。
・フィールドを持つことが出来ない。
・インターフェイスのメソッドは全て抽象メソッドにしなければならず、実装を持てない
・メンバーは全てpublic扱いで、privateなどにできない
・staticな静的メンバーを持つことが出来ない
C# 8.0以降のインターフェイス
ところがC# 8.0からは上記のようなインターフェイスの制約は撤廃されました。C# 8.0からはインターフェイスで以下のようなことができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
interface Animal
{
private static String animal_j = “動物”;
private void Disp_Str()
{
Console.WriteLine(animal_j + “が歩く。”);
}
public void Walk()
{
Disp_Str();
}
}
class Dog : Animal
{
}
public static void Main()
{
Animal a = new Dog();
a.Walk();
}
|
機能が強化されたインターフェイス
上のC#サンプルを実行すると、以下のように表示されます。
動物が歩く。
DogクラスにはWalkメソッドが無いので、インターフェイスで実装したWalkの処理が呼ばれています。インターフェイスではC# 8.0以前ではできなかったstaticなフィールドやprivateもこのように利用できます。
ただしstaticではない動的なフィールドは、C# 8.0以降のインターフェイスでも持つことはできません。抽象クラスのインターフェイスに対する優位性は、動的なフィールドを持てることだけになったと言えます。
- SE
- なるほど。C#のabstractclassを知ることで、オブジェクト指向についての理解も深まりそうですね。
- PM
- その通りです。しっかり理解して、活用してください。
C#のabstract classを使いこなそう
C#のabstract classについて解説しましたが、ご理解頂けましたでしょうか。
似た機能を持つインターフェイスも併せて紹介しましたが、開発現場においては抽象クラスよりインターフェイスの方が相応しいケースが多いと思われます。抽象クラスの使い道は抽象的な親クラスを1つだけ持たせたい時に限りますが、それが必要な時は是非活用しましょう。
Search キーワード検索
Popular 人気の記事
-
.NET Framework 3.5をWindows10にインストールする方法
2019年10月24日 -
【VB.NET入門】DataGridViewの使い方まとめ
2019年12月22日 -
EdgeとChromeはどう違う?それぞれのスペック7つを比較解説!
2020年09月28日 -
VB.NETとは?特徴や他言語と比べておすすめできる理由も解説!
2019年12月21日 -
【VB.NET入門】学ぶメリット・知識ゼロから始める手順全まとめ!
2019年12月21日
reccomended おすすめ記事
-
C#のusingステートメントでリソースの解放【Disposeとの違いとは】
2020年03月17日 -
【SQL Serverログの操作】トランザクションログの使用量を確認する方法
2020年03月16日 -
【.NETが統合】.NET 5の概要と今後のリリース予定
2020年03月05日