また、一方が他方を意味しますか?
8 に答える
強く型付けされた言語と静的に型付けされた言語の違いは何ですか?
静的に型付けされた言語には、コンパイル時に実装 (コンパイラまたはインタープリター) によってチェックされる型システムがあります。型チェックは一部のプログラムを拒否し、チェックに合格したプログラムには通常、いくつかの保証が付いています。たとえば、コンパイラは、浮動小数点数に対して整数算術命令を使用しないことを保証します。
「厳密に型付けされた」言語の定義で最も広く使用されているのは、「厳密に型付けされた」言語では、プログラマーが型システムによって課せられた制限を回避することはできないというものですが、「厳密に型付けされた」とはどういう意味かについて実際の合意はありません。 . この用語は、ほとんどの場合、静的に型付けされた言語を説明するために使用されます。
静的 vs 動的
静的型付けの反対は「動的型付け」です。つまり、
- 実行時に使用される値は、タイプに分類されます。
- このような値の使用方法には制限があります。
- これらの制限に違反すると、違反は (動的) タイプのエラーとして報告されます。
たとえば、動的型付け言語であるLuaには、文字列型、数値型、ブール型などがあります。Lua では、すべての値は厳密に1 つの型に属しますが、これはすべての動的型付け言語の要件ではありません。Lua では、2 つの文字列を連結することは許可されていますが、文字列とブール値を連結することは許可されていません。
強い vs 弱い
「強く型付けされた」の反対は「弱く型付けされた」であり、型システムを回避できることを意味します。C は型付けが弱いことで有名です。キャストするだけで、任意のポインター型を他のポインター型に変換できるからです。Pascal は厳密に型付けされることを意図していましたが、設計上の見落とし (タグ付けされていないバリアント レコード) により、型システムに抜け穴が生じたため、技術的には弱く型付けされています。厳密に型指定された言語の例には、CLU、標準 ML、Haskell などがあります。実際、標準 ML は、言語が広く展開された後に発見された型システムの抜け穴を取り除くために、いくつかの改訂を受けています。
ここで実際に何が起こっているのですか?
全体として、「強い」と「弱い」について話すことはあまり役に立たないことがわかりました。型システムに抜け穴があるかどうかは、抜け穴の正確な数と性質、それらが実際に発生する可能性、および抜け穴を悪用した結果がどうなるかよりも重要ではありません。実際には、「強い」と「弱い」という用語を一緒に避けるのが最善です。
アマチュアはしばしばそれらを「静的」と「動的」と混同します。
どうやら「弱いタイピング」は、暗黙の変換の相対的な普及または欠如について話すために一部の人によって使用されています。
専門家は、用語が何を意味するのかについて正確に同意することはできません.
全体として、聴衆に情報を提供したり啓発したりする可能性は低いです。
悲しいことに、型システムに関して言えば、「強い」と「弱い」の技術的な意味について、普遍的に合意されたものはありません。 型システムの相対的な強さについて議論したい場合は、提供されている保証と提供されていない保証について正確に議論することをお勧めします。たとえば、「特定の型 (またはクラス) のすべての値は、その型のコンストラクターの 1 つを呼び出すことによって作成されたことが保証されていますか?」という質問をするのが良いでしょう。C では、答えはノーです。CLU、F#、および Haskell では、yes です。C++ についてはわかりませんが、知りたいです。
対照的に、静的型付けは、プログラムが実行される前にチェックされることを意味し、プログラムは開始前に拒否される可能性があります。 動的型付けとは、実行中に値の型がチェックされることを意味し、型付けが不適切な操作により、プログラムが停止したり、実行時にエラーが発生したりする可能性があります。静的型付けの主な理由は、そのような「動的型エラー」を持つ可能性のあるプログラムを除外することです。
一方が他方を暗示していますか?
専門的なレベルでは、いいえ、「強い」という言葉は実際には何の意味もないからです。しかし実際には、ほとんどの場合、人々は次の 2 つのいずれかを行います。
彼らは (誤って) 「強い」と「弱い」を「静的」と「動的」を意味するために使用しています。
「強い」と「弱い」を使用して、静的型システムのプロパティを比較します。誰かが「強い」または「弱い」動的型システムについて話しているのを聞くことは非常にまれです。FORTH を除いて、型システムのようなものはまったくありませんが、動的に型付けされた言語で型システムを覆すことは考えられません。定義によると、これらのチェックは実行エンジンに組み込まれており、すべての操作は実行前に健全性がチェックされます。
いずれにせよ、ある言語を「強く型付けされた」と呼ぶ場合、その人は静的に型付けされた言語について話している可能性が非常に高くなります。
これはよく誤解されているので、はっきりさせておきます。
静的/動的型付け
静的型付けは、型が変数にバインドされる場所です。タイプはコンパイル時にチェックされます。
動的型付けは、型が値にバインドされる場所です。タイプは実行時にチェックされます。
たとえば、Javaでは次のようになります。
String s = "abcd";
s
「永遠に」なりますString
。String
その存続期間中、それは異なるsを指す場合がs
あります(Javaでの参照であるため)。null
値がある場合もありますが、Integer
またはを参照することはありませんList
。それは静的型付けです。
PHPの場合:
$s = "abcd"; // $s is a string
$s = 123; // $s is now an integer
$s = array(1, 2, 3); // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class
それが動的型付けです。
強い/弱いタイピング
(アラートを編集してください!)
強い型付けとは、広く合意された意味のないフレーズです。この用語を静的型付け以外の意味で使用するほとんどのプログラマーは、コンパイラーによって強制される型の規律があることを意味するためにこの用語を使用します。たとえば、CLUには強力な型システムがあり、型によって提供されるコンストラクターを使用する場合を除いて、クライアントコードが抽象型の値を作成することはできません。Cはやや強い型システムを持っていますが、プログラムは常にあるポインタ型の値を別のポインタ型の値にキャストできるため、ある程度「破壊」される可能性があります。したがって、たとえば、Cでは、によって返された値を取得してmalloc()
、元気ににキャストできFILE*
ます。コンパイラは、あなたを止めようとはしません。また、危険なことをしていることを警告することもありません。
(元の回答は、「実行時に型を変更しない」という値について何かを述べていました。私は多くの言語デザイナーやコンパイラー作成者を知っていて、実行時に型を変更する値について話している人を知りませんでした。システム。これは「強力な更新の問題」として知られています。)
弱いタイピングは、コンパイラがタイピングの規律を強制しないこと、またはおそらく強制が簡単に覆される可能性があることを意味します。
この回答の原文は、弱い型付けと暗黙の変換(「暗黙の昇格」とも呼ばれる)を混同していました。たとえば、Javaの場合:
String s = "abc" + 123; // "abc123";
これは暗黙的なプロモーションの例です。123は、と連結される前に暗黙的に文字列に変換されます"abc"
。Javaコンパイラはそのコードを次のように書き直していると主張することができます。
String s = "abc" + new Integer(123).toString();
古典的なPHPの「で始まる」問題を考えてみましょう。
if (strpos('abcdef', 'abc') == false) {
// not found
}
ここでのエラーはstrpos()
、0である一致のインデックスを返すことです。0はブール値false
に強制変換されるため、条件は実際には真です。解決策は、暗黙の変換を回避する===
代わりにを使用することです。==
この例は、暗黙的な変換と動的型付けの組み合わせがプログラマーを迷わせる可能性があることを示しています。
それをRubyと比較してください。
val = "abc" + 123
これは実行時エラーです。Rubyでは、オブジェクト123がメソッドに渡されたという理由だけで、オブジェクト123が暗黙的に変換されないためです。+
Rubyでは、プログラマーは変換を明示的にする必要があります。
val = "abc" + 123.to_s
PHPとRubyを比較することは、ここでの良い例です。どちらも動的型付け言語ですが、PHPには多くの暗黙の変換があり、Rubyにはありません(おそらく、それに慣れていない場合は驚くべきことです)。
静的/動的vs強い/弱い
ここでのポイントは、静的/動的軸が強/弱軸から独立しているということです。強い型と弱い型が明確に定義されていないだけでなく、強い型と弱い型が何を意味するのかについて実際のコンセンサスがないため、人々はおそらくそれらを混乱させます。このため、強い/弱いタイピングは、黒や白ではなく、はるかに灰色の陰影になります。
だからあなたの質問に答える:これを見る別の方法はほとんど正しいですが、静的型付けはコンパイル時の型の安全性であり、強い型付けは実行時の型の安全性であると言うことです。
この理由は、静的に型付けされた言語の変数には、宣言する必要があり、コンパイル時にチェックできる型があるためです。強く型付けされた言語には、実行時に型を持つ値があり、プログラマーが動的チェックなしで型システムを破壊することは困難です。
ただし、言語は静的/強い、静的/弱い、動的/強い、または動的/弱い可能性があることを理解することが重要です。
どちらも2つの異なる軸上の極です。
- 強い型と弱い型
- 静的型付けと動的型付け
強く型付けされているということは、変数が1つの型から別の型に自動的に変換されないことを意味します。弱い型付けはその逆です。Perlは、文字列"123"
を自動的にintに変換することにより、数値コンテキストのように文字列を使用できます123
。Pythonのような強く型付けされた言語はこれを行いません。
静的に型付けされたとは、コンパイラーがコンパイル時に各変数の型を把握することを意味します。動的型付け言語は、実行時に変数の型を把握するだけです。
強く型付けされているということは、型間の変換の間に制限があることを意味します。
静的に型付けされるということは、型が動的ではないことを意味します。変数が作成されると、変数の型を変更することはできません。
Data Coercion は必ずしも弱い型付けを意味するとは限りません。
上記の Java の例は、以下の理由で型付けが弱い
String s = "abc" + 123;
実際に行っているため、弱く型付けされた例ではありません。
String s = "abc" + new Integer(123).toString()
新しいオブジェクトを作成する場合、データ強制も弱く型付けされません。Java は弱い型付けの非常に悪い例です (そして、適切なリフレクションを持つ言語は、ほとんどの場合、弱い型付けではありません)。言語のランタイムは型が何であるかを常に認識しているためです (例外はネイティブ型である可能性があります)。
これは C とは異なります。C は、弱い型付けの最良の例の 1 つです。ランタイムは、4 バイトが整数、構造体、ポインター、または 4 文字のいずれであるかを認識しません。
言語のランタイムは、それが弱く型付けされているかどうかを実際に定義します。
EDIT: さらに考えた後、ランタイムは厳密に型指定されたシステムであるためにランタイムシステムですべての型を具体化する必要がないため、これは必ずしも真実ではありません。Haskell と ML には完全な静的分析があるため、ランタイムから型情報を省略できる可能性があります。
一方は他方を意味しません。言語が静的に型付けされるということは、コンパイル時にすべての変数の型が既知であるか推測されることを意味します。
強く型付けされた言語では、ある型を別の型として使用することはできません。Cは弱い型の言語であり、強い型の言語では許可されない良い例です。Cでは、間違ったタイプのデータ要素を渡すことができ、文句を言うことはありません。強く型付けされた言語ではできません。
強力な型付けとは、おそらく、変数の型が明確に定義されており、式で異なる型の変数を組み合わせることについて厳密な規則があることを意味します。たとえば、A が整数で B が float の場合、A+B に関する厳密な規則は、A が float にキャストされ、結果が float として返されることです。A が整数で B が文字列の場合、A+B は有効ではないという厳密な規則が適用される可能性があります。
静的型付けとは、おそらく、型がコンパイル時 (またはコンパイルされていない言語の場合はそれに相当するもの) に割り当てられ、プログラムの実行中に変更できないことを意味します。
これらの分類は相互に排他的ではないことに注意してください。実際、これらは頻繁に一緒に発生すると予想されます。多くの厳密に型指定された言語も静的に型指定されています。
また、「おそらく」という言葉を使用するとき、これらの用語の普遍的に受け入れられている定義がないためであることに注意してください. これまでの回答からすでにわかるように。