C#のabstract classとは?インターフェイスについても併せて解説!

- システム
エンジニア - C#のabstractclassはとても難しいですね。
- プロジェクト
マネージャー - そうかもしれませんが、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以降のインターフェイスでも持つことはできません。抽象クラスのインターフェイスに対する優位性は、動的なフィールドを持てることだけになったと言えます。
- システム
エンジニア - なるほど。C#のabstractclassを知ることで、オブジェクト指向についての理解も深まりそうですね。
- プロジェクト
マネージャー - その通りです。しっかり理解して、活用してください。
C#のabstract classを使いこなそう
C#のabstract classについて解説しましたが、ご理解頂けましたでしょうか。
似た機能を持つインターフェイスも併せて紹介しましたが、開発現場においては抽象クラスよりインターフェイスの方が相応しいケースが多いと思われます。抽象クラスの使い道は抽象的な親クラスを1つだけ持たせたい時に限りますが、それが必要な時は是非活用しましょう。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


C#新着案件New Job
-
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(新宿駅) -
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(新宿駅) -
デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円神奈川県横浜市(桜木町駅) -
デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円神奈川県横浜市(桜木町駅) -
基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(西新宿駅) -
基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(西新宿駅)