「ダック・タイピング」の版間の差分
編集の要約なし |
|||
13行目: | 13行目: | ||
== Rubyでの例 == |
== Rubyでの例 == |
||
Rubyでの単純な例を示す。 |
Rubyでの単純な例を示す。 |
||
< |
<syntaxhighlight lang="ruby"> |
||
def test(foo) |
def test(foo) |
||
puts foo.sound |
puts foo.sound |
||
32行目: | 32行目: | ||
test(Duck.new) |
test(Duck.new) |
||
test(Cat.new) |
test(Cat.new) |
||
</syntaxhighlight> |
|||
</source> |
|||
出力は以下である。 |
出力は以下である。 |
||
42行目: | 42行目: | ||
== C++での例 == |
== C++での例 == |
||
上記Rubyの例をC++で記述すると、以下のようになる。 |
上記Rubyの例をC++で記述すると、以下のようになる。 |
||
< |
<syntaxhighlight lang="cpp"> |
||
#include <iostream> |
#include <iostream> |
||
66行目: | 66行目: | ||
test(Cat()); |
test(Cat()); |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
実行結果はRubyの例と同じである。ただし、テンプレートによるダック・タイピングはコンパイル時に解決される静的なポリモーフィズムであり、動的型付け言語とは異なり実行時のオーバーヘッドを伴わない。 |
実行結果はRubyの例と同じである。ただし、テンプレートによるダック・タイピングはコンパイル時に解決される静的なポリモーフィズムであり、動的型付け言語とは異なり実行時のオーバーヘッドを伴わない。 |
||
72行目: | 72行目: | ||
C#はバージョン4.0で動的型付けを可能にする<code>dynamic</code>型が使えるようになった。<code>dynamic</code>は内部的には[[リフレクション (情報工学)|リフレクション]]を利用して実装されており、該当するメソッドやプロパティの存在有無を実行時に遅延評価する。 |
C#はバージョン4.0で動的型付けを可能にする<code>dynamic</code>型が使えるようになった。<code>dynamic</code>は内部的には[[リフレクション (情報工学)|リフレクション]]を利用して実装されており、該当するメソッドやプロパティの存在有無を実行時に遅延評価する。 |
||
< |
<syntaxhighlight lang="csharp"> |
||
using System; |
using System; |
||
97行目: | 97行目: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
なお、C#はC++のテンプレートに似た機能として[[ジェネリクス]]をサポートするが、C++テンプレートほどの柔軟性はなく、ダック・タイピングに使用することはできない<ref>[https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/differences-between-cpp-templates-and-csharp-generics Differences Between C++ Templates and C# Generics - C# Programming Guide | Microsoft Docs]</ref>。 |
なお、C#はC++のテンプレートに似た機能として[[ジェネリクス]]をサポートするが、C++テンプレートほどの柔軟性はなく、ダック・タイピングに使用することはできない<ref>[https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/differences-between-cpp-templates-and-csharp-generics Differences Between C++ Templates and C# Generics - C# Programming Guide | Microsoft Docs]</ref>。 |
||
106行目: | 106行目: | ||
下記の例は、<code>Option Strict On</code>を指定すると静的な型チェックが有効になり、コンパイルエラーになる。 |
下記の例は、<code>Option Strict On</code>を指定すると静的な型チェックが有効になり、コンパイルエラーになる。 |
||
< |
<syntaxhighlight lang="vb.net"> |
||
Option Strict Off ' 遅延バインディングを許可する。 |
Option Strict Off ' 遅延バインディングを許可する。 |
||
'Option Strict On ' 遅延バインディングを許可しない。 |
'Option Strict On ' 遅延バインディングを許可しない。 |
||
133行目: | 133行目: | ||
End Sub |
End Sub |
||
End Class |
End Class |
||
</syntaxhighlight> |
|||
</source> |
|||
== その他の言語など == |
== その他の言語など == |
2020年7月5日 (日) 22:49時点における版
ダック・タイピング(英: duck typing)とは、Smalltalk、Perl、Python、Rubyなどのいくつかの動的型付けオブジェクト指向プログラミング言語に特徴的な型付けの作法のことである。それらの言語ではオブジェクト(変数の値)に何ができるかはオブジェクトそのものが決定する。これによりポリモーフィズム(多態性)を実現することができる。つまり、静的型付け言語であるJavaやC#の概念で例えると、オブジェクトがあるインタフェースのすべてのメソッドを持っているならば、たとえそのクラスがそのインタフェースを宣言的に実装していなくとも、オブジェクトはそのインタフェースを実行時に実装しているとみなせる、ということである。それはまた、同じインタフェースを実装するオブジェクト同士が、それぞれがどのような継承階層を持っているのかということと無関係に、相互に交換可能であるという意味でもある。
この用語の名前は「ダック・テスト」に由来する。
"If it walks like a duck and quacks like a duck, it must be a duck"
(もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルに違いない)
デーブ・トーマスはRubyコミュニティで初めてこの言葉を使ったと考えられている。
C++のテンプレートはダック・タイピングの静的版である。例えば、STLにおける各種のiteratorはIterator基底クラスのようなものからメソッドを継承しているわけではないが、同じ構文でコンパイルが通るならば、それはiteratorの一種として扱える。この文脈で言う「同じインタフェースを持つ」とは、コンパイラにとってシグネチャなどのインタフェースが同じだということである。したがって、iteratorの実装はオブジェクトである必要すらない。
もう1つ、ダック・タイピングに似たアプローチにOCamlのstructural subtypingがある。メソッドのシグネチャが互換ならば、宣言上の継承関係は関係なくとも、オブジェクトの型は互換であるというものである。これはOCamlの型推論システムによってコンパイル時にすべて決定される。
Rubyでの例
Rubyでの単純な例を示す。
def test(foo)
puts foo.sound
end
class Duck
def sound
'quack'
end
end
class Cat
def sound
'myaa'
end
end
test(Duck.new)
test(Cat.new)
出力は以下である。
quack myaa
2つのクラスに継承の関係が無いことに注目して欲しい。
C++での例
上記Rubyの例をC++で記述すると、以下のようになる。
#include <iostream>
template <class T>
void test(const T& t) {
std::cout << t.sound() << std::endl;
}
struct Duck {
const char* sound() const {
return "quack";
}
};
struct Cat {
const char* sound() const {
return "myaa";
}
};
int main() {
test(Duck());
test(Cat());
}
実行結果はRubyの例と同じである。ただし、テンプレートによるダック・タイピングはコンパイル時に解決される静的なポリモーフィズムであり、動的型付け言語とは異なり実行時のオーバーヘッドを伴わない。
C#での例
C#はバージョン4.0で動的型付けを可能にするdynamic
型が使えるようになった。dynamic
は内部的にはリフレクションを利用して実装されており、該当するメソッドやプロパティの存在有無を実行時に遅延評価する。
using System;
class Duck {
public string Sound() {
return "quack";
}
}
class Cat {
public string Sound() {
return "myaa";
}
}
public class DuckTypingTest {
static void Test(dynamic obj) {
Console.WriteLine(obj.Sound());
}
public static void Main() {
Test(new Duck());
Test(new Cat());
}
}
なお、C#はC++のテンプレートに似た機能としてジェネリクスをサポートするが、C++テンプレートほどの柔軟性はなく、ダック・タイピングに使用することはできない[1]。
VB.NET
Visual Basic .NET (VB.NET) はOption Strict Off
が指定されている場合、System.Object
型による遅延バインディング (late binding) ができるようになり、これによりダック・タイピングをサポートできる[2][3]。これは、VB.NETが登場当初から従来のVisual BasicおよびVisual Basic for Applications (VBA) からの移行を狙っていたため、ゆるい型付けをサポートする必要があったことに由来する。
下記の例は、Option Strict On
を指定すると静的な型チェックが有効になり、コンパイルエラーになる。
Option Strict Off ' 遅延バインディングを許可する。
'Option Strict On ' 遅延バインディングを許可しない。
Imports System
Class Duck
Public Function Sound() As String
Return "quack"
End Function
End Class
Class Cat
Public Function Sound() As String
Return "myaa"
End Function
End Class
Public Class DuckTypingTest
Shared Sub Test(obj As Object)
Console.WriteLine(obj.Sound())
End Sub
Public Shared Sub Main()
Test(new Duck())
Test(new Cat())
End Sub
End Class
その他の言語など
Javaは言語構文レベルで動的型付けをサポートしないが、リフレクションを用いることで、ダック・タイピング相当を実現できる。Core Reflection APIとして、java.lang.reflect
パッケージが用意されている[4]。また、Java Native Interface (JNI) を用いることで、C言語やC++などのネイティブコードからJavaで書かれたクラスを利用することができるが、リフレクション同様にダック・タイピングに応用することもできる。
COMにおいても、IDispatch
インタフェース[5]を実装することで、ダック・タイピング相当を実現できる。VBScriptやJScriptといったスクリプト言語(動的プログラミング言語)の実装を容易にするための基盤として、拡張インタフェースIDispatchEx
も用意されている[6]。
脚注
- ^ Differences Between C++ Templates and C# Generics - C# Programming Guide | Microsoft Docs
- ^ Object Variable Declaration - Visual Basic | Microsoft Docs
- ^ Early and Late Binding - Visual Basic | Microsoft Docs
- ^ Java Core Reflection
- ^ IDispatch Interface and Accessibility - Windows applications | Microsoft Docs
- ^ IDispatchEx Interface | Microsoft Docs
関連項目
外部リンク
この節に雑多な内容が羅列されています。 |
この節の出典は、Wikipedia:信頼できる情報源に合致していないおそれがあります。 |