静的/動的vs強/弱


319

私はこれらの用語がプログラミングのあちこちに散らばっているのを見て、私はそれらが何を意味するのか漠然とした考えを持っています。検索の結果、スタックオーバーフロー全体でそのようなことが要求されていることがわかりました。私の知る限り、言語での静的/動的型付けは、厳密/弱い型付けとは微妙に異なりますが、その違いが何であるかわかりません。ソースが異なれば、意味も異なるように見えるか、用語を同じ意味で使用しているように見えます。両方について話し、実際に違いを説明している場所はどこにもありません。誰かがこれを私と世界の残りのためにここに明確に綴ってくれればいいのですが。



回答:


423
  • 静的/動的型付けとは型情報が取得されるとき(コンパイル時または実行時)のことです。

  • 厳密/弱い型付けとは、型を厳密に区別する方法(言語が文字列から数値への暗黙の変換を試みるかどうか)です。

詳細については、wikiページを参照してください。


7
ウィキペディアにはすべての答えがあります。なぜこれに遭遇しなかったのか、私にはわかりません。
Dan Revell

31
静的/動的が強い/弱い以外の何かであることを多くの人が知らないのは残念です...それは本当にいくつかのバイアスと議論を救うでしょう。
Dykam 2010

10
「型の弱点」にはさまざまな程度があります。強く型付けされた言語は、文字列から数値への変換を試みる可能性があります。一方、HyperTalk(私が数十年前に使用した言語)は弱く型付けされているため、"12" + "34"と等しくなりますが"46""12" + "34Q"等しくなります"1234Q"(幸い、"12" & "34"連結が必要な場合は記述できます)。奇妙なことに、数値を保持する変数は倍精度浮動小数点数としてそれらを格納し、そのような変数の計算では文字列を変更せずに浮動小数点値を使用しましたが、変数が文字列か数値かを確認する方法がありませんでした。
スーパーキャット2012年

9
@kittylyst私はこの答えが強いが静的の同義語であることを示唆している場所を見ることはできません
ピート

4
++(ほぼ)単一行の定義。
JamesFaix、2016年

211

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

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

強く型付けされた言語の実装は、多くの場合、時間の経過とともに抜け穴を獲得するため、通常はランタイムシステムの一部を高水準言語で実装できます。たとえば、Objective Camlには呼び出された関数Obj.magicがあり、実行時に引数を返すだけの効果がありますが、コンパイル時に任意の型の値を他の任意の型の1つに変換します。私のお気に入りの例はModula-3で、デザイナーは型キャスト構成体と呼んでいLOOPHOLEます。

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


31
(+1)「強い」および「弱い」という用語を避けるための提案。
ニコ、

1
同意して、ちょうどジョン・スキートの本を読んでいました、そしてこれはそこで述べられた同じ応答です。
Bennett Yeates 2017年

私の知る限りでは、Javaにもこれらの抜け穴がありますが、Javaは依然として強く型付けされた言語と見なされているため、「強い」および「弱い」という用語を避けるというアドバイスに、より重きを置いていると思います。
doubleOrt 2018

74

簡単に言えば、静的に型付けされた言語では、型はstaticです。つまり、変数を型に設定すると、変更できなくなります。これは、タイピングが参照する値ではなく変数に関連付けられているためです。

たとえばJavaの場合:

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

のに対して動的型付け言語の種類があり、ダイナミックあなたが型に変数を設定した後、あなたはそれを変更することができることを意味し、。これは、タイピングが変数ではなく値に関連付けられているためです。

たとえばPythonでは:

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

一方、言語の強い/弱い型付けは、暗黙的な型変換に関連しています(@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.

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


2
すばらしい答え、そして具体的な例を使用するための称賛。
ジュリアンA.

3
これが、PHPを慎重に使用する必要がある理由です。
Ali Gajani 2016年

1
言語の例は本当に役に立ちます。とても有難い。
J Mullen 2017

この意味で、非文字列を文字列と連結できるため、および自動アンボクシング/ボクシングのために、Javaの型付けはこれまでわずかに弱くなりますか?
スティーブンポール

1
@StephenPaul正解私の答えはそのように理解されるかもしれませんし、そうではありません。単純化のために連結を使用しましたが、実際には、強さ/弱さは変数自体の暗黙的な型変換に関するものです。
メフメット

20

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

別の種類の弱く型付けされた言語はCで、メモリアドレスのデータをキャストすることで別の型として扱うことができます。

強く型付けされた言語では、オブジェクトの型は変わりません-intは常にintであり、それを文字列として使用しようとすると、エラーが発生します。JavaとPythonはどちらも厳密に型指定されています。

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

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

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


1
この文に同意できません-。「静的に型付けされた言語では、すべての変数とパラメーターの型をソースで宣言する必要があります」-SMLでは、変数の型を宣言する必要はありません(どのようにチェックされるか)。関数fが引数xfun f(x))[**型が宣言されていない**]を取り、関数の本体がであるとしましょうx+1。タイプが宣言されてxいない場合、コンパイラはint でなければならないことを理解します。- fun f x = x + 1; val f = fn : int -> int
Filip Bartuzi 2014年

Cに関しては、キャストは5 + 'c' // OK
厳密

3
@mehmet:Cでは、文字値は整数ドメインにあるため、特定の例はタイプセーフに違反しません。'c'は99の単なる構文糖です。Cには専用の文字タイプはありません。
Peter Lewerin 2017年

ピーター・ルウェリン:そうだね、もっと良い例を挙げるべきだった。残念ながら、それは私がC :)触れていないので、ほぼ20年が経ちました
メフメト

1
Cは弱く型付けされた言語ではありません。これは、Java、C#などがCと比較してより強く型付けされた言語であるということだけです。続きを読む-en.wikipedia.org/wiki/Strong_and_weak_typing 「弱く」型付けされた言語の定義をチェックすると、「弱く」型付けされた言語たとえば、intを「暗黙的に」変換または文字列にキャストできるなど、任意のタイプの変換を実行できるものがありますが、Cでこれが可能かどうかを考えてみてください。
hagrawal 2017

15

今日、このテーマについて研究していると、この素晴らしい記事に出くわしました。http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html私と私にとっては、上記の素晴らしい答えのいくつかに追加される可能性があると思いました。

強くて弱いタイピング:

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

静的型と動的型

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

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

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

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


8

スコットのプログラミング言語プラグマティクス、第3版の291ページから、

型チェックは、プログラムが言語の型互換性規則に準拠していることを確認するプロセスです。ルールの違反はタイプクラッシュと呼ばれます。言語の実装が強制できる方法で、その操作をサポートすることを意図していないオブジェクトへの操作の適用を禁止する場合、その言語は強く型付けされていると言われます。言語が強く型付けされ、コンパイル時に型チェックを実行できる場合、その言語は静的に型付けされているといいます。厳密に言えば、静的に型付けされる言語はほとんどありません。実際には、用語は多くの場合、ほとんどの型チェックをコンパイル時に実行でき、残りは実行時に実行できる言語に適用されます。

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

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

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

私はスコットの説明を素敵な図に翻訳しようとしました。

静的/動的-強い/弱いタイピングプレーン


5

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

ここに2つの例があります:

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

  • 他の人(ダリオの見解など)は、意図的に文字列から数値に暗黙的に変換できる言語は型付けが弱いと言いますが、これを単にダック型と呼ぶ人もいます。

どちらのステートメントも、型システムの両極端ではなく、完全に異なる側面を強調しています。ラムゼイ氏の見解では、型システムを区別するために「強い」と「弱い」という用語を使用しないようにしています。


5

静的対動的型付け言語

  • 静的に型付けされた言語は、コンパイル時に型チェックが行われる言語であるため、静的に型付けされた言語では、各変数に型があり、コースを通じて変更されません。これとは対照的に、動的に型付けされた言語は、実行時に型チェックが行われ、コンパイル時に型チェックが行われないため、動的に型付けされた言語では、変数に関連付けられた型がある場合とない場合があります。、そして型が関連付けられている場合、JSの「var」のようなジェネリック型であり、文字列と数値の両方に適しています。
    • 「動的に型チェックされる言語の実装では、通常、各ランタイムオブジェクトを、型情報を含む型タグ(つまり、型への参照)に関連付けます。このランタイムタイプ情報(RTTI)は、動的ディスパッチ、遅延バインディング、ダウンキャスト、リフレクション、および同様の機能を実装するためにも使用できます。」
  • 言語が静的に型付けされている場合でも、動的に型付けされた機能が含まれている可能性があります。これは、基本的に、実行時に何らかの種類の型チェックも行われることを意味します。これは型のキャストに役立ちます。
    • 「ダウンキャストなど、多くの便利で一般的なプログラミング言語機能を静的にチェックすることはできません。したがって、多くの言語には静的型チェックと動的型チェックの両方があります。静的型チェッカーが可能なことを検証し、動的型チェッカーが残りを検証します。」
  • 「一部の言語では、タイプセーフではないコードを記述できます。たとえば、Cでは、プログラマは同じサイズの2つの型の間で値を自由にキャストできます。」
  • 「静的」型付き言語の利点は次のとおりです。
    • ほとんどの型チェックはコンパイル時に行われるため、インタープリターまたはランタイムは、型について心配することなく、フルスピードで実行できます。
    • ほとんどの型チェックはコンパイル時に行われるため、型に関連する実行時例外またはエラーの数が少なくなります。
  • 「動的に」型付けされた言語の利点は次のとおりです。
    • 開発者が型システムを理解する必要がないので、開発者は変数を緩く作成して実行できるため、これらは非常に高速なプロトタイピングに役立ち、これにより非常に高速なプロトタイピングが可能になります。
  • 静的および動的に型付けされた言語のリスト
    • 静的に:
      • ジャワ
      • C(Cは静的に型付けされた言語ですが、より暗黙的な変換が可能なため、Javaに比べて「強く」型付けされていません)
      • C ++
      • C#
    • 動的に:
      • PERL
      • PHP
      • パイソン
      • JavaScript
      • ルビー
  • 型チェックは重要なセキュリティ機能です。タイプチェックがなく、メソッドが「creditAccount(BankAccountDetails)」と呼ばれるメソッドを持つタイプ「BankAccount」のオブジェクトを受け入れるとします。実行時にタイプチェックがない場合は、自分のオブジェクトを渡すことができます。同じメソッド「creditAccount(BankAccountDetails)」を持つクラス。オブジェクト指向言語について話していることを考えると、OOPは「ポリモーフィズム」をサポートしており、ここで説明するのは「ポリモーフィズム」だけです。したがって、強力な型チェックを持たない基本的にオブジェクト指向言語(つまり、「ポリモーフィズム」をサポートすることを意味します)は、セキュリティの問題を引き起こす可能性があります。

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

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

さらに良い読み


あなたは「実行時に型チェックがない場合は実行時に、同じメソッド「creditAccount(BankAccountDetails)」を持つ自分のクラスのオブジェクトを渡すことができます」-オブジェクトを渡すことをブロックする可能性のあるメカニズムをすでに超えている場合次に、型チェックにより、静的に型付けされた言語の場合に、そのメソッドを呼び出すことができなくなりますか?
Aseem Yadav '25

@AseemYadav「*オブジェクトを渡すことを妨げる可能性のあるメカニズムをすでに超えている場合」とはどういう意味ですか?
hagrawal 2017

あなたが言及したように、それは重要なセキュリティ機能であり、同じメソッドで自分のクラスのオブジェクトを渡すこともできるので、他の誰かのコードに侵入しようとしたときにのみ脆弱性のように思われ、セキュリティに関連する問題よりもパフォーマンスの問題よりも、自分に属するコードのコンテキストで話をしている場合は、そうではありませんか。
Aseem Yadav 2017

これにはパフォーマンスの側面はありません。ポリモーフィズムのコンテキストから確認する必要があります。そうすると、セキュリティの側面を理解できるようになります。これについては、同じ段落で説明しました。
hagrawal 2017

1

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

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

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

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

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

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

String a = "123"
int b = (int)a;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.