Link and Motivation Developers' Blog

リンクアンドモチベーションの開発者ブログです

色々なオブジェクト指向言語の型システムを比較してみた

はじめに

オブジェクト指向言語を対象に、型に関する情報をまとめてみました。
誤り、改善箇所がありましたらコメントいただけますと幸いです。

公開当時(2020/12)の情報を基に書いています。

 比較表

言語名 登場年 ①検査タイミング ②指定方法 ③互換性の確認方法
Smalltalk 1980 動的 暗黙的 ダックタイプ的
Ada 1983 静的 明示的 名前的
C++ 1983 静的
ときどき動的
明示的
ときどき暗黙的
名前的
ときどき構造的
Objective-C 1984 静的
ときどき動的
明示的
ときどき暗黙的
名前的
ときどきダックタイプ的
Eiffel 1985 静的 明示的 名前的
Object Pascal 1986 静的 明示的 名前的
Perl 1987 動的 暗黙的 ダックタイプ的
Python 1990 動的 暗黙的
ときどき明示的
ダックタイプ的
ときどき名前的
Lua 1993 動的 暗黙的 ダックタイプ的
Java 1995 静的 明示的
ときどき暗黙的
名前的
PHP 1995 動的 暗黙的
ときどき明示的
ダックタイプ的
ときどき名前的
JavaScript 1995 動的 暗黙的 ダックタイプ的
Ruby 1995 動的 暗黙的 ダックタイプ的
C# 2000 静的
ときどき動的
明示的
ときどき暗黙的
名前的
ときどきダックタイプ的
Visual Basic .NET 2001 静的
ときどき動的
明示的
ときどき暗黙的
名前的
ときどきダックタイプ的
Scala 2003 静的 明示的
ときどき暗黙的
名前的
ときどき構造的
D 2007 静的
ときどき動的
明示的
ときどき暗黙的
名前的
ときどき構造的
Go 2009 静的 明示的
ときどき暗黙的
構造的
ときどき名前的
ときどきダックタイプ的
Rust 2010 静的 明示的
ときどき暗黙的
名前的
Kotlin 2011 静的 明示的
ときどき暗黙的
名前的
Dart 2011 静的
ときどき動的
明示的
ときどき暗黙的
名前的
TypeScript 2012 静的
ときどき動的
明示的
ときどき暗黙的
構造的
Swift 2014 静的 明示的
ときどき暗黙的

名前的
ときどき構造的

①検査タイミング

比較表にもどる ↩

 📝 分類

 ⅰ. 静的な検査 static checking

実行前に検査する方式。

 ⅱ. 動的な検査 dynamic checking

実行時に検査する方式。


 🔦 特徴的なケース

 ケース1. オブジェクトだけ実行時に検査する

該当:Objective-C

Objective-Cコンパイル型言語なのですが、オブジェクトの型だけは実行時に決定します。

 ケース2. コンパイル時に決まらない分は実行時に検査する

該当:Dart, TypeScript

静的な検査で型が決まらなくてもエラーにせず、実行時の検査で問題があればそのタイミングでエラーとしています。

②指定方法

比較表にもどる ↩

 📝 分類

 ⅰ. 明示的な指定 explicit specification

プログラムの要素に対して特定の型を指定する様に記述する方式。

 
// int型を明示している
int number = 123;

 ⅱ. 暗黙的な指定 implicit specification

明示的な指定の反対。特定の型を指定しない方式。

 
# 型を明示しない
number = 123

 🔦 特徴的なケース

大まかには下記の傾向があります。

  • 検査が静的なら明示的な指定をする
  • 検査が動的なら暗黙的な指定をする

が、そう単純でないケースも有ったので紹介します。

 ケース1. 検査は静的だが型推論で一部の指定を省略できる

該当する言語:C++, Java, C#, Scala, D, Go, Rust, Kotlin, Dart, TypeScript, Swift

 
// 型の指定は無いが、123を代入してるのでintと決定する
val x = 123

 ケース2. 通常時の検査は静的だが、専用の構文で指定を省略すると検査が動的になる

該当する言語:C++, C#

 
// 型の指定は無いが、実行時に動的に決定する
dynamic number = someNumber;

 ケース3. 検査は動的だが明示的な指定ができる

該当する言語:Python, PHP

 
// 型の指定に基づき、代入可能か実行時に検査する
public int $number = 123;

 ケース4. 明示的な指定を強制するか選べる

該当する言語:Visual Basic .NET

Visual Basic .NET
 
Option Strict On ' 明示的な指定を強制する設定

' 中略

Dim number As Integer = 123

 ③互換性の確認方法

比較表にもどる ↩

 📝 分類

 ⅰ. 名前的な互換性 nominal compatibility

名前によって決める方式。

 
// User型が期待されている。右辺も同じくUser型だから代入可能
User user = new User();

 ⅱ. 構造的な互換性 structural compatibility

静的な検査時の構造によって決める方式。

ⅲ. ダックタイプ的な互換性 duck type compatibility

動的な検査時1の構造によって決める方式。


 🔦 特徴的なケース

 ケース1. 通常は「名前的」だが、テンプレートを使うと「構造的」になる

該当:C++, D

通常時は「名前的」ですが
次の様にテンプレートを使うと「構造的」になります。

 
// 引数には`std::string name()`の構造が期待されている
template<class T> std::string user_name(T user) {
   return user.name();
}

 ケース2. 通常は「構造的」だが、比較対象同士の型が名前をもつなら「名前的」にもなる

該当:Go

Go
 
// `Name() string`の構造が期待されている
var user interface { Name() string }

// Userと同じ構造が期待されている
// ただし、同じ構造でもUser以外の名前の型なら代入できない(匿名なら代入可)
var user User

 ケース3. 対象の型に応じて異なる方式を使い分ける

該当:Swift

Swiftでは

  • 関数とタプルだけ「構造的」
  • 他は「名前的」

このように方式を使い分けています。

※この記事は2020年12月22日にQiitaへ投稿した記事の転載です

参考文献

Pierce, B. C., & C., B. (2002). Types and programming languages. MIT Press.

バートランド・メイヤー. (2008). オブジェクト指向入門: 方法論・実践.

増井敏克. (2017). プログラミング言語図鑑: プログラミング言語の現在・過去・未来...知ればもっと楽しめる!

Comparison of programming languages by type system. (2016, May 22). - Wikipedia. Retrieved December 24, 2020, from https://en.m.wikipedia.org/wiki/Comparison_of_programming_languages_by_type_system

Type system. (2003, March 22). - Wikipedia. Retrieved December 24, 2020, from https://en.m.wikipedia.org/wiki/Type_system

なぜGoはDuck typingを採用していると言えるのか、データ構造から詳しく解説してみた. (2020, January 26). Qiita. Retrieved December 24, 2020, from https://qiita.com/ttiger55/items/ecf6765847faacf9a60b


  1. ダックタイプ(ダックタイピング)という語は、「動的な検査時」に限定しない意味で使うことも有る様です。が、曖昧さの無い他の言葉が見つからなかったので、採用しました。