web-dev-qa-db-ja.com

静的/動的vs強/弱

私はこれらの用語がプログラミングのいたるところに散らばっているのを見て、それらが何を意味するのか漠然とした概念を持っています。実際にスタックオーバーフローが発生すると、そのようなことが求められていることが検索でわかります。私の知る限り、言語での静的/動的型付けは、強い/弱い型付けとは微妙に異なりますが、その違いは私には分かりません。異なるソースは異なる意味を使用しているか、用語を同じ意味で使用しているようです。私は両方について話している場所を見つけることができず、実際に違いを説明しています。誰かがこれを私と他の世界のためにここではっきりと説明してくれたらいいと思う。

294
Dan Revell
  • Static/Dynamic Typingis aboutwhen型情報が取得されます(コンパイル時または実行時)

  • Strong/Weak Typingは約厳密な型の区別(例:言語が文字列から数値への暗黙的な変換)。

詳細については wiki-page をご覧ください。

388
Dario

アマチュアがプログラミング言語について話すために使用する用語のソフトスポットを発見しました。 「強い」および「弱い」タイピングという用語は使用しないでください。それらは技術的な意味について普遍的に合意されていないためです。対照的に、静的タイピングは、プログラムが実行前にチェックされるであることを意味し、プログラムは開始前に拒否される可能性があります。 動的タイピングは、valuesのタイプがチェックされていることを意味しますduring実行、および不適切な型指定の操作により、プログラムが停止するか、そうでない場合実行時にエラーを通知する。静的型付けの主な理由は、このような「動的型エラー」が発生する可能性のあるプログラムを除外することです。

厳密な型指定は一般に、型システムに抜け穴なしがあることを意味しますが、弱い型付けは型システムを破壊できることを意味します(保証を無効にします) 。この用語は、静的タイピングと動的タイピングを意味するためにしばしば誤って使用されます。違いを確認するには、Cを考えてください。言語はコンパイル時に型チェックされます(静的型付け)が、抜け穴がたくさんあります。任意の型の値を同じサイズの別の型にキャストできます。特に、ポインタ型を自由にキャストできます。パスカルは強く型付けされることを意図した言語でしたが、有名ではない予期せぬ抜け穴がありました:タグのない異形レコードです。

強く型付けされた言語の実装は、通常、時間の経過とともに抜け穴を獲得するため、通常はランタイムシステムの一部を高レベル言語で実装できます。たとえば、Objective CamlにはObj.magicと呼ばれる関数があり、単に引数を返すだけのランタイム効果がありますが、コンパイル時に任意の型の値を他の型のいずれかに変換します。私のお気に入りの例はModula-3で、その設計者は型キャスト構造LOOPHOLEを呼び出しました。

そうは言っても、まったく同じように「強い」と「弱い」という言葉を使用している2人を当てにすることはできません。避けてください。

201
Norman Ramsey

静的に型付けされた言語では、型はstaticです。つまり、変数を型に設定すると、変更することはできません。これは、入力が変数が参照する値ではなく変数に関連付けられているためです。

たとえば、Javaの場合:

String str = "Hello";  //statically typed as string
str = 5;               //would throw an error since Java is statically typed

一方、動的に型付けされた言語型はdynamicです。つまり、変数を型に設定した後、それを変更できます。これは、入力が変数ではなく値に関連付けられているためです。

たとえば、Pythonの場合:

str = "Hello" # it is a string
str = 5       # now it is an integer; perfectly OK

一方、言語のstrong/weakタイピングは、暗黙的な型変換に関連しています(@Darioの回答から一部取得)。

たとえば、Pythonの場合:

str = 5 + "hello" 
# would throw an error since it does not want to cast one type to the other implicitly. 

一方、PHPの場合:

$str = 5 + "hello"; // equals 5 because "hello" is implicitly casted to 0 
// PHP is weakly typed, thus is a very forgiving language.

静的型付けでは、コンパイル時に型の正確性を確認できます。通常、静的に型付けされた言語はコンパイルされ、動的に型付けされた言語は解釈されます。したがって、動的に型指定された言語は、実行時に型指定をチェックできます。

65
mehmet

弱い型付けとは、コンテキストに応じてオブジェクトの型を変更できることを意味します。たとえば、弱い型付けの言語では、文字列「123」に別の数字を追加すると、数字の123として扱われる場合があります。タイピングの弱い言語の例は、bash、awk、PHPです。

別の種類の弱い型付け言語はCで、メモリアドレスのデータはキャストによって異なる型として扱うことができます。

強く型付けされた言語では、オブジェクトの型は変わりません。intは常にintであり、文字列として使用しようとするとエラーになります。 JavaとPythonの両方が強く型付けされています。

動的型付けと静的型付けの違いは、型規則が適用される場合です。静的に型付けされた言語では、すべての変数とパラメーターの型はソースで宣言する必要があり、コンパイル時に適用されます。動的に型指定された言語では、型は実行時に使用されるときにのみチェックされます。したがって、Javaは静的に型付けされ、Pythonは動的に型付けされます。

ただし、境界は時々少しぼやけることがあります。たとえば、Javaは静的に型指定されますが、リフレクションまたはキャストを使用するたびに(たとえば、オブジェクトのコンテナを使用する場合)、型チェックをランタイムに延期します。

同様に、最も強く型付けされた言語は、整数と浮動小数点の間で自動的に変換されます(一部の言語では、任意精度のBigInts)。

19
Dave Kirby

今日、この主題について研究していると、この素晴らしい記事に出会いました http://blogs.Perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html =それは私のために多くのことを片付け、私はそれが上記の素晴らしい答えのいくつかを追加するかもしれないと思った。

強く弱い入力:

おそらく、型システムが分類される最も一般的な方法は「強い」または「弱い」です。これらの単語にはほとんど意味がないため、これは残念です。限られた範囲で、2つの言語を非常に類似したタイプのシステムと比較し、1つをこれら2つのシステムのより強力なものとして指定することができます。それを超えて、言葉は何も意味しません。

静的および動的タイプ

これは、実際の意味を持つ型システムの唯一の一般的な分類です。実際のところ、その重要性は過小評価されていることがよくあります[...]動的型システムと静的型システムは、まったく異なる2つのものであり、その目標は部分的に重複しています。

静的型システムとは、コンパイラがソースコードを調べ、ラベル(「型」と呼ばれる)を構文の各部分に割り当て、それらを使用してプログラムの動作について何かを推測するメカニズムです。動的型システムは、プログラムが使用するデータの種類(偶然にも「型」とも呼ばれる)を追跡するためにコンパイラがコードを生成するメカニズムです。これら2つのシステムのそれぞれで同じWordの「タイプ」を使用することは、もちろん完全に偶然ではありません。それでも、それは一種の弱い歴史的重要性を持つものとして最もよく理解されています。 「タイプ」が実際に両方のシステムで同じことを意味する世界観を見つけようとすると、大きな混乱が生じます。そうではありません。

明示的/暗黙的なタイプ:

これらの用語が使用される場合、それらはコンパイラーがプログラムの部分の静的タイプについて推論する範囲を指します。すべてのプログラミング言語には、型に関する何らかの推論があります。他の人よりも多い人もいます。 MLとHaskellには暗黙の型があり、型宣言は必要ありません(使用している言語と拡張機能に応じて、ごくわずかです)。 JavaとAdaは非常に明示的な型を持ち、物の型を常に宣言しています。上記のすべてには、(たとえば、CやC++と比較して)強力な静的型システムがあります。

13
gonz

ScottのProgramming Language Pragmatics、第3版のページ291から、

型チェックは、プログラムが言語の型互換性ルールに従っていることを確認するプロセスです。ルールの違反は、型の衝突として知られています。言語は、言語の実装が強制できる方法で、オブジェクトに対する操作の適用を禁止している場合、強く型付けされていると言われていますその操作をサポートするためのものではありません。言語が厳密に型指定されており、コンパイル時に型チェックを実行できる場合、言語は静的に型指定されたと言われます。厳密に言うと、静的に型付けされる言語はほとんどありません。実際には、この用語は多くの場合、コンパイル時にほとんどの型チェックを実行でき、残りは実行時に実行できる言語に適用されます。

いくつかの例:Adaは強く型付けされており、大部分は静的に型付けされています(実行時に特定の型制約をチェックする必要があります)。 Pascal実装はコンパイル時にほとんどの型チェックを行うこともできますが、言語は厳密には型付けされていません。タグ付けされていないバリアントレコード(セクション7.3.4で説明)が唯一の抜け穴です。 C89は、その前の方言よりも大幅に強く型付けされていますが、それでもPascalよりもかなり強く型付けされていません。その抜け穴には、ユニオン、変数の数が可変のサブルーチン、およびポインターと配列の相互運用性(セクション7.7.1で説明)が含まれます。 Cの実装は、実行時にほとんど何もチェックしません。

動的(実行時)型チェックは遅延バインディングの形式であり、実行時まで他の問題を遅らせる言語で見られる傾向があります。 LISPとSmalltalkは動的に(強く)入力されます。ほとんどのスクリプト言語も動的に入力されます。いくつか(例:PythonやRuby)は強く型付けされています。動的スコープを持つ言語は一般に動的に型付けされます(またはまったく型付けされません):コンパイラが名前が参照するオブジェクトを識別できない場合、通常はオブジェクトの型も判別できません。

簡単に言えば、静的/動的型付けは型チェックが発生する時間を指します。静的型付けのコンパイル時間と動的言語の実行時間です。同様に、強い/弱い型付けは、言語がその型システムを強制することにどれほど積極的かを指します。

スコットの説明をニースの図に変換しようとしました。これを以下に投稿しました。

The Static/Dynamic - Strong/Weak Typing Plane

6
Evan Rosica

私は他の同僚が特に良い仕事をしたと思います。静的タイピングと動的タイピングの違いを説明します。しかし、強い型付けと弱い型付けに関する限り、異なる理解/見解があると言われるべきです。

以下に2つの例を示します。

  • any型変換を行うことが許可されていないため、Haskellは強く型付けされていると言う人もいます。

  • 他の人(例:Darioの見解)は、意図的に暗黙的に文字列から数字に変換できる言語は弱い型付けであると言いますが、他の人でさえこれを単なるダックタイピングと呼びます。

両方のステートメントは、型システムの反対の極端ではなく、完全に異なる側面を強調しています。そこで私は、タイプシステムを区別するために「強い」と「弱い」という用語を使用しないというラムジー氏の見解に加わります。

5
Nico

静的v/s動的型付け言語

  • 静的に型付けされた言語は、コンパイル時に型チェックが行われる言語であるため、これは、静的に型付けされた言語では各変数に型があり、コース上で変化しないことも意味します対照的に、動的に型付けされた言語は、実行時に型チェックが行われる言語であり、コンパイル時に型チェックが行われないため、これも意味します動的に型付けされた言語では、変数に関連付けられた型がある場合とない場合があります。ま​​た、型が関連付けられている場合は、JSの「var」のような汎用型であり、文字列と数字の両方。
    • 「動的に型チェックされた言語の実装は、通常、各ランタイムオブジェクトを、その型情報を含む型タグ(つまり、型への参照)に関連付けます。このランタイムタイプ情報(RTTI)は、動的ディスパッチ、遅延バインディング、ダウンキャスト、リフレクション、および同様の機能の実装にも使用できます。
  • 言語が静的に型付けされている場合でも、動的に型付けされた機能を持つ可能性があります。これは基本的に、実行時に何らかの型チェックも行うことを意味します。これは、型のキャストに役立ちます。
    • 「ダウンキャストなど、多くの便利で一般的なプログラミング言語機能を静的にチェックすることはできません。したがって、多くの言語では静的および動的の両方の型チェックが行われます。静的型チェッカーが可能なことを検証し、動的チェックが残りを検証します。」
  • 「一部の言語では、タイプセーフではないコードを記述できます。たとえば、Cでは、プログラマは同じサイズを持つ2つの型の間で値を自由にキャストできます。」
  • 「静的に」型付けされた言語の利点は次のとおりです:
    • ほとんどの型チェックはコンパイル時に行われるため、インタープリターまたはランタイムは型を気にせずに最高速度で実行できます。
    • ほとんどの型チェックはコンパイル時に行われるため、型に関連するランタイム例外またはエラーの数が少なくなります。
  • 「動的に」型付けされた言語の利点は次のとおりです:
    • 開発者は型システムを理解する必要がないため、開発者は変数を緩やかに作成して実行できるため、非常に高速なプロトタイプ作成に役立ちます。これにより、非常に高速なプロトタイプ作成が可能になります。
  • 静的および動的に型付けされた言語のリスト
    • 静的:
      • Java
      • C (C is a statically typed language but lesser “strongly” typed as compared to Java because it allows more implicit conversions)
      • C++
      • C#
    • 動的に:
      • Perl
      • PHP
      • Python
      • JavaScript
      • Ruby
  • 型チェックは重要なセキュリティ機能です。型チェックがなく、メソッドが呼び出されるメソッドを持つ「BankAccount」タイプのオブジェクトを受け入れるとします「creditAccount(BankAccountDetails)」として、実行時に型チェックがない場合、同じメソッド「creditAccount(BankAccountDetails)」を持つ独自のクラスのオブジェクトを渡すことができ、オブジェクト指向について話していることを考慮して実行されますなぜなら、OOPは「多態性」をサポートしており、ここで議論しているのは「多態性」に他ならないからです。そのため、基本的に強力な型チェックを持たないオブジェクト指向言語(基本的に「多態性」をサポートすることを意味します)は、セキュリティの問題につながる可能性があります。

強く型付けされた弱い型付け言語

  • 厳密に型指定された言語は、精度が失われた場合に暗黙の変換が許可されない言語です。たとえば、Javaでは、精度の損失がないため「intからlong」をキャストできますが、精度の損失があるため「暗黙的に」「longからint」をキャストできません。対照的に、型指定の弱い言語では、精度が失われても暗黙的な変換が許可されます。
  • 動的に型付けされた言語は、「実行時」に精度が失われる暗黙的な変換が許可されない場合、強く型付けされた言語にもなり得ると思います。

さらに良い読み物

4
hagrawal

通常、静的に型付けされた言語では、変数の型を宣言する必要があります。変数の型は、エラーを減らすためにコンパイル時にチェックされます。 「静的に型付けされた」の「静的」という言葉は、「静的コード分析」を指します。これは、実行前にコードを調べるプロセスです。静的に型付けされた言語では、式または実際のパラメーターの右側から変数の型を推測することは可能ですが、実際にはほとんどの静的に型付けされた言語では変数型を明示的に宣言する必要があります。

動的型付け言語は通常、変数宣言に型を持つ必要はなく、すべての割り当てステートメントの右側または関数呼び出しの実際のパラメーターを評価した結果として計算された型に基づいて変数型を推測します。変数には、その存続期間中に複数の割り当てを与えることができるため、その型は時間とともに変化する可能性があり、これが「動的型付け」と呼ばれる理由です。また、ランタイム環境では各変数の現在の型を追跡する必要があるため、型は変数宣言ではなく値にバインドされます。これは、ランタイムタイプ情報(RTTI)システムと見なすことができます。

静的および動的に型付けされた言語の要素を組み合わせることができます。たとえば、C#は静的および動的に型指定された変数の両方をサポートし、オブジェクト指向言語は一般に型階層のダウンキャストをサポートします。静的に型付けされた言語は、通常、型チェックをバイパスするさまざまな方法を提供します。たとえば、キャスト、リフレクション、および動的呼び出しを使用します。

強い型と弱い型は、変数が実際には別の型であるかのように1つの型であるかのように変数を使用することにより、言語がバグを防止しようとする連続性を指します。たとえば、CとJavaはどちらも静的に型付けされた言語ですが、JavaはCよりも強力な型チェックを使用します。次のCコードはコンパイルして実行し、ランダムに実行時に変数bに値を入れると、ほとんどの場合バグが発生します。

char *a = "123";
int b = (int)a;

同等のJavaコードは、一般的に望ましいコンパイルエラーを生成します。

String a = "123"
int b = (int)a;
1
Danger

私は最近、この正確なトピックを説明する記事を書きました:

https://dev.to/jiangh/type-systems-dynamic-versus-static-strong-versus-weak-b6c

0
Hong Jiang