C#の仮想メソッド(virtual)と抽象メソッド(abstract)の違いを徹底解説
仮想メソッドと抽象メソッドの基本的な違い
抽象メソッド(abstract)は実装を持たず、メソッドの定義(シグネチャ)のみを持ちます。抽象クラス内でのみ宣言でき、派生クラスに対して必ずオーバーライドすることを強制します。
一方、仮想メソッド(virtual)は抽象メソッドとは異なり、基底クラス側に実装を持ちます。抽象クラスでも通常のクラスでも宣言でき、派生クラスはオーバーライドするかどうかを自由に選択できます。
| 比較項目 | 仮想メソッド(virtual) | 抽象メソッド(abstract) |
|---|---|---|
| 実装 | あり(既定の処理を提供) | なし(定義のみ) |
| オーバーライド | 任意 | 必須 |
| 宣言できるクラス | 抽象クラス・通常クラスの両方 | 抽象クラスのみ |
| 呼び出しの決定タイミング | 実行時(ポリモーフィズム) | 実行時(ポリモーフィズム) |
仮想メソッド(virtual)とは
C#の virtual キーワードは、メソッド、プロパティ、インデクサー、イベントを修飾するために使用します。基底クラスで定義した関数を、継承先のクラスで独自の実装に差し替えたい場合に仮想関数を利用します。仮想関数は継承クラスごとに異なる実装が可能で、どの実装が呼び出されるかは実行時に決定されます。
仮想メソッドの宣言例は次のとおりです。
public virtual int area() { }仮想メソッドのサンプルコード
using System;
namespace PolymorphismApplication {
class Shape {
protected int width, height;
public Shape( int a = 0, int b = 0) {
width = a;
height = b;
}
public virtual int area() {
Console.WriteLine("Parent class area :");
return 0;
}
}
class Rectangle: Shape {
public Rectangle( int a = 0, int b = 0): base(a, b) {
}
public override int area () {
Console.WriteLine("Rectangle class area ");
return (width * height);
}
}
class Triangle: Shape {
public Triangle(int a = 0, int b = 0): base(a, b) {
}
public override int area() {
Console.WriteLine("Triangle class area:");
return (width * height / 2);
}
}
class Caller {
public void CallArea(Shape sh) {
int a;
a = sh.area();
Console.WriteLine("Area: {0}", a);
}
}
class Tester {
static void Main(string[] args) {
Caller c = new Caller();
Rectangle r = new Rectangle(10, 7);
Triangle t = new Triangle(10, 5);
c.CallArea(r);
c.CallArea(t);
Console.ReadKey();
}
}
}実行結果
Rectangle class area Area: 70 Triangle class area: Area: 25
この例では、Caller クラスの CallArea メソッドは Shape 型の引数を受け取りますが、実際に渡されたオブジェクトが Rectangle か Triangle かに応じて、それぞれのクラスでオーバーライドされた area() が実行時に呼び出されます。これがポリモーフィズム(多態性)の典型的な動作です。
抽象メソッド(abstract)とは
C#の abstract キーワードは、抽象クラスおよび抽象メソッドの宣言に使用します。抽象クラスには、抽象メソッドと非抽象メソッド(通常のメソッド)の両方を含めることができます。なお、抽象メソッドを持つクラスは必ず抽象クラスとして宣言する必要があり、抽象クラスは直接インスタンス化できない点にも注意しましょう。
次に、C#の抽象クラス内で抽象メソッドを使用する例を示します。
抽象メソッドのサンプルコード
using System;
public abstract class Vehicle {
public abstract void display();
}
public class Bus : Vehicle {
public override void display() {
Console.WriteLine("Bus");
}
}
public class Car : Vehicle {
public override void display() {
Console.WriteLine("Car");
}
}
public class Motorcycle : Vehicle {
public override void display() {
Console.WriteLine("Motorcycle");
}
}
public class MyClass {
public static void Main() {
Vehicle v;
v = new Bus();
v.display();
v = new Car();
v.display();
v = new Motorcycle();
v.display();
}
}実行結果
Bus Car Motorcycle
この例では、抽象クラス Vehicle の display() を、Bus、Car、Motorcycle の各派生クラスがそれぞれオーバーライドしています。変数 v の型は Vehicle ですが、代入されたインスタンスに応じて異なる display() が呼び出される点に注目してください。
まとめ
仮想メソッドは「既定の実装を持ち、上書きは任意」、抽象メソッドは「実装を持たず、派生クラスによる実装が必須」というのが最大の違いです。共通のデフォルト動作を提供したい場合は virtual を、派生クラスに必ず固有の実装を強制したい場合は abstract を選ぶとよいでしょう。
-
DirectX11とDirectX12の違いを徹底解説!ゲーマーが知っておくべきポイント
DirectXは、ソフトウェアがマルチメディアコンテンツを描画し、グラフィックハードウェアと通信するために使用されるAPI(アプリケーションプログラミングインターフェース)のコレクションです。DirectXの主要な構成要素であるDirect3Dは、ソフトウェアとグラフィックスハードウェア間の通信を担っています。ハードウェアは製品ごとに異なるため、標準化された関数や呼び出しのライブラリを通じてグラフィックカードと通信することで、ゲーム開発を大幅にスピードアップできます。これは「ハードウェア抽象化」と呼ばれ、APIの最も重要な役割となっています。車に例えてみましょう。1台の車の運転ができれば、ほぼ
-
JavaScriptにおける関数とメソッドの違いとは?わかりやすく解説
JavaScriptにおいて、関数とメソッドは本質的には同じものです。両者の違いは、メソッドがオブジェクトのプロパティとして定義された関数であるという点にあります。つまり、独立して定義されたものを「関数」、オブジェクトに紐づけられたものを「メソッド」と呼びます。 JavaScriptの関数の基本形 まず、一般的な関数の定義方法を見てみましょう。 function functionname(param1, param2){ // 処理内容 } JavaScriptのメソッドの例 メソッドは、オブジェクトに関連付けられた関数です。次の例では、employeeオブジェクトの中にdetails