抽象型(ちゅうしょうがた、)とは、コンピュータプログラミングの型システムのうち、名前的型システム () における型の一種であり、直接インスタンス化することができないという特徴を持つ。対義語は具象型()であり、具象型はインスタンス化することができる。抽象型の変数に格納された実際の値は、何らかの (existential type) を持つMitchell, John C.; Plotkin, Gordon D.; Abstract Types Have Existential Type, ACM Transactions on Programming Languages and Systems, Vol. 10, No. 3, July 1988, pp. 470–502。

抽象型は実装を提供しないか、あるいは不完全な実装を提供する。具体的な形態や仕様はプログラミング言語ごとに異なるが、いくつかの言語において、実装を持たない抽象型はインタフェース (interface) や (protocol) などと呼ばれている。クラスベースのオブジェクト指向プログラミング言語では、抽象型は抽象クラス (abstract class) として実装され、具象型は具象クラス (concrete class) として実装される。

例えばJavaでの抽象型は、抽象クラスとインタフェースである。ただし抽象クラスはabstractという宣言が付与されたクラスのことであり、抽象メソッドを含むこともあれば、含まないこともあるAbstract Methods and Classes (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)。また、メソッドのシグネチャを一切含まない空のインタフェースを定義することもできる。

抽象型の表記方法

抽象クラスは、以下のようないくつかの方法で生成され、示され、シミュレートされる。 JavaやC#では、クラス定義の際に明示的にキーワード abstract を付与することで抽象クラスであることを示す。 クラス定義の中で、クラスがそのプロトコルの一部として受容することを宣言されているが、実装は提供されないメソッド(抽象メソッド、C++では純粋仮想関数と呼ぶ)を含む場合、そのクラスは抽象クラスである。 抽象型を継承するが、実装が必要な機能(抽象メソッド)をすべてオーバーライドしないクラスもまた抽象クラスである。 Smalltalkなどの動的型付き言語では、自分自身 (this) へ送信するメソッドが実装されていない場合、そのクラスは抽象クラスと見なせる。(ただし、このような実装は単なるバグの可能性もあり、実行してみるまでエラーであることが検出できない。)

抽象型の性質 抽象型は、静的型付けのオブジェクト指向言語において重要な機能である。動的型付き言語の場合は、ダック・タイピングがあるので抽象型は不要であり、等価な機能は存在しないものが多かったが、名前的型付け (nominal typing) の安全性や利便性を享受する観点から抽象型を導入した事例もある29.7. abc --- 抽象基底クラス — Python 3.6.13 ドキュメント。

派生型のないクラスを「リーフクラス」とし、それ以外を抽象クラスに分類している書籍もある。

抽象型は、派生型が実装すべきメソッド群をプロトコルとして規定することができる。抽象型のインスタンスは直接生成できず、派生型は全ての必要な機能を実装しなければならない。このことはプログラムの正当性を保証する役割を担っている。

抽象型の種類

抽象クラス(実装継承と型継承の混合) オブジェクト指向言語における抽象クラスとは、abstractを明示的に宣言されたクラスか、抽象メソッド(メソッドシグネチャの宣言のみで、実際のコードが実装されていないメソッド)を含むクラスである。通常のクラスと異なり、インスタンス化はできない。 実装の多重継承には技術的問題があるため、多くのオブジェクト指向言語では、直接には単一の基底クラスしか継承できない。複数の基底型から成る派生型の定義 (subtyping) をサポートするため、多重継承を「実装継承」ではなく「型継承」に限定する目的で、抽象クラスとは別の純粋な抽象型(インタフェース)を定義する機構を備えた言語もある。

インタフェース(純粋な型継承) Javaなどにはインタフェースがある。Javaのインタフェースはメソッドのシグネチャや定数を持つことができるが、メソッドの実装や変数(フィールド)を持つことはできない。Javaのクラスは複数のインタフェースを実装 (implement) できる。インタフェースは抽象メンバーのみを含む抽象クラスに似ているが、多重継承できる点が異なる。 Java 8やC# 8のように、言語仕様の改訂によりインタフェースに静的メソッドを定義したり、デフォルト実装を提供したりすることもできるようになったケースもあるDefault Methods (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)インターフェイス - C# リファレンス | Microsoft Docs。 Javaにおける抽象クラスは、インタフェースを実装し、いくつかのメソッドのシグネチャを定義していることもあるが、一方でキーワード abstract により抽象化されたままのメソッドを持っている。クラスが実装すると宣言したインタフェースのすべてのメソッドの実装を提供していない場合、そのクラスはabstractとして宣言されなければならない。 C#では、クラスが実装すると宣言したインタフェースのすべてのメソッドの実装を提供する必要がある。

プロトコル(純粋な型継承) Objective-CとSwiftにはプロトコルがあるコードをもっとオブジェクティブに:Cocoaの素、Objective-Cを知ろう(6)(2/4 ページ) - @ITProtocols — The Swift Programming Language (Swift 5.5)。プロトコルはメソッドやプロパティの宣言を持つことができるが、それらの実装や変数(状態)を持つことはできない。Objective-Cのクラスや、Swiftのクラス・構造体・列挙型は複数のプロトコルを採用 (adopt) できる。 Objective-CとSwiftのプロトコルでは、インスタンスメンバーだけでなく、クラスメンバー(静的メンバー)の宣言を持つこともできる。プロトコルを採用する型は、それらの実装を提供しなければならない。プロトコルのメンバーにはrequiredとoptionalの種別があり、requiredの実装は必須だが、optionalの実装は任意である。 Swift 2.0では、プロトコル拡張 (protocol extension) により、既存のプロトコルにメソッドの実装やcomputedプロパティの実装を追加することができるようになったSwiftにおけるプロトコル指向プログラミング | InfoQProtocols — The Swift Programming Language (Swift 5.5), §Protocol Extensions。プロトコル拡張により、メソッドやプロパティのデフォルト実装を提供することもできる。Swiftの「拡張」はObjective-Cの「カテゴリ」に似た言語機能であり、既存の型に対して変更を加えることなく機能を追加することができるExtensions — The Swift Programming Language (Swift 5.5)。ただし、プロトコル自身は依然として実装や状態を持つことはできない。

トレイト(Mix-inでの機能)

型クラス(アドホック多相由来のジェネリック・サブタイピング)

脚注 注釈

出典

参考文献

Types and Programming Languages by Benjamin Pierce (MIT Press 2002) More Effective C++: 35 New Ways to Improve Your Programs and Designs by Scott Meyers (1995) ISBN 0-201-63371-X

外部リンク

Traits: Composable Units of Behavior by Nathanael Schärli, Stéphane Ducasse, Oscar Nierstrasz and Andrew Black

関連項目 インタフェース (抽象型) 型システム 型理論

sv:Klass (programmering)#Abstrakt klass