ダックタイピングは、古い「バリアント」型やインターフェースとどう違うのでしょうか? 質問する

ダックタイピングは、古い「バリアント」型やインターフェースとどう違うのでしょうか? 質問する

「ダック タイピング」というフレーズが頻繁に使われ、コード例もいくつか見かけました。 自分で調査する暇もなく、とても 忙しい のですが、誰か簡単に教えてもらえませんか。

  • 「アヒル型」と昔ながらの「変異型」の違い、そして
  • バリアント型付けよりもダック型付けを好む例を示し、
  • 私が望むことの例を挙げてください持っているダックタイピングを使用して達成するには?

ダックタイピングのイラストはThe Registerより提供

この「新しい」概念の力を疑って不潔な印象を与えるつもりはありませんし、調査を拒否して問題から逃げるつもりもありませんが、最近このことに関して見聞きする大騒ぎに私はうんざりしています。いいえ私にとっては、型付け (つまり動的型付け) が初めてなので、すぐには利点がわかりません。

追記: これまでの例に感謝します。 'O->can(Blah)' のようなものを使用することは、リフレクション検索 (おそらく安価ではない) を行うことと同等であり、(O is IBlah) と言っているのとほぼ同じであるように思われます。これはコンパイラがチェックできる可能性がありますが、後者には、他の 2 つとは異なり、私の IBlah インターフェイスとあなたの IBlah インターフェイスを区別できるという利点があります。確かに、すべてのメソッドに多数の小さなインターフェイスが存在すると、混乱が生じますが、多数の個別のメソッドをチェックするのも混乱を招きます...

...またしても理解できません。これは素晴らしい時間節約になるのでしょうか、それとも新品の袋に入ったいつもの物なのでしょうか?必要ダックタイピング?

ベストアンサー1

ここでの回答の中には、用語の誤った使用法が見られ、人々が間違った回答をする原因となっています。

そこで、答える前に、いくつかの定義を示します。

  1. 強く型付けされた

    言語は、プログラムの型安全性を強制する場合、強く型付けされています。つまり、言語は、進行と呼ばれるものと保存と呼ばれるものの 2 つを保証します。進行とは、基本的に、すべての「有効な型付け」のプログラムが実際にコンピューターで実行できることを意味します。クラッシュしたり、例外をスローしたり、無限ループで実行されたりする可能性がありますが、実際には実行できます。保存とは、プログラムが「有効な型付け」されている場合、常に「有効な型付け」であり、割り当てられた型に準拠しない値が変数 (またはメモリ ロケーション) に含まれないことを意味します。

    ほとんどの言語には「進行」特性があります。しかし、「保存」特性を満たさない言語も数多くあります。良い例は C++ (および C も) です。たとえば、C++ では、任意のメモリ アドレスを任意の型のように動作するように強制できます。基本的に、これによりプログラマーはいつでも型システムを侵害できます。簡単な例を次に示します。

    struct foo
    {
        int x;
        iny y;
        int z;
    }
    
    char * x = new char[100];
    foo * pFoo = (foo *)x;
    foo aRealFoo;
    *pFoo = aRealFoo;
    

    このコードにより、文字の配列を取得して、それに「foo」インスタンスを書き込むことができます。C++ が厳密に型指定されている場合、これは不可能です。C#、Java、VB、lisp、ruby、python などの型安全な言語では、文字の配列を「foo」インスタンスにキャストしようとすると例外がスローされます。

  2. 弱い型付け

    強く型付けされていない場合は、弱く型付けされます。

  3. 静的型付け

    言語の型システムがコンパイル時に検証される場合、その言語は静的に型付けされます。静的に型付けされた言語は、C のように「弱い型付け」か、C# のように強い型付けのいずれかになります。

  4. 動的型付け

    動的型付け言語とは、実行時に型が検証される言語です。多くの言語では、静的型付けと動的型付けが何らかの形で混在しています。たとえば、C# では、コンパイル時にチェックできないため、多くのキャストを実行時に動的に検証します。他の例としては、Java、VB、Objective-C などの言語があります。

    「Lisp」、「Ruby」、「Small Talk」のように、「完全に」または「ほとんど」動的に型付けされる言語もいくつかあります。

  5. ダックタイピング

    ダック タイピングは、静的、動的、弱い、または強い型付けとはまったく直交するものです。これは、基礎となる型の ID に関係なく、オブジェクトで機能するコードを記述する手法です。たとえば、次の VB.NET コードがあります。

    function Foo(x as object) as object
        return x.Quack()
    end function
    

    「Foo」に渡されるオブジェクトの型が何であっても、「Quack」というメソッドが定義されている限り、動作します。つまり、オブジェクトがアヒルのように見え、アヒルのように歩き、アヒルのように話すなら、それはアヒルです。ダック タイピングにはさまざまな形式があります。静的ダック タイピング、動的ダック タイピング、強いダック タイピング、弱いダック タイピングが可能です。C++ テンプレート関数は「弱い静的ダック タイピング」の良い例です。「JaredPar」の投稿に示されている例は「強い静的ダック タイピング」の例を示しています。VB (または Ruby や Python のコード) の遅延バインディングにより、「強い動的ダック タイピング」が可能になります。

  6. 変異体

    バリアントは、文字列、整数型、日付、COM オブジェクトなど、さまざまな定義済みデータ型を保持できる動的に型付けされたデータ構造です。バリアントに格納されたデータの割り当て、変換、操作を行うための一連の操作を定義します。バリアントが強く型付けされているかどうかは、それが使用される言語によって異なります。たとえば、VB 6 プログラムのバリアントは強く型付けされています。VB ランタイムは、VB コードで記述された操作がバリアントの型付け規則に準拠することを保証します。VB でバリアント型を介して IUnknown に文字列を追加しようとすると、ランタイム エラーが発生します。ただし、C++ では、すべての C++ 型が弱く型付けされているため、バリアントは弱く型付けされています。

さて、定義がわかったので、あなたの質問に答えることができます。

VB 6 のバリアントは、ダック タイピングの 1 つの形式を可能にします。バリアントよりもダック タイピングを実行する優れた方法 (Jared Par の例は最も優れた例の 1 つです) はありますが、バリアントを使用してダック タイピングを実行することができます。つまり、基礎となる型の ID に関係なく、オブジェクトを操作する 1 つのコードを記述できます。

ただし、バリアントを使用してこれを行うと、実際には十分な検証は得られません。JaredPar が説明しているような静的に型付けされたダック タイプ メカニズムでは、ダック タイピングの利点に加えて、コンパイラによる追加の検証も得られます。これは非常に役立ちます。

おすすめ記事