動的タイプ、静的タイプを一般的に理解する.強いタイプ、弱いタイプ

5433 ワード

0 x 01引用
今日、ある友达とC++が强いタイプなのか弱いタイプなのかを话した时、彼は私にC++が强いタイプなのかと教えてくれた.彼は私にC++が书く时にint、floatなどのキーワードで変数を定义する必要があるので、C++は强いタイプなのかと言った.私は彼にC++が弱いタイプなのかと言ったが、彼は意外にも私が基础が分からないと嘲笑した.
私はまた別の学友Pythonが強いタイプなのか弱いタイプなのかを聞いてみたが、得られたのは意外にも弱いタイプで、定義変数にintがないので、float!
それから私はいくつかのネット上の資料を探して彼らに間違っていることを伝えようとしたが、その結果、ネット上の資料の多くは厳格な結果のために簡単な問題(実は簡単ではない)を複雑に言っていることが分かった.例えば、知っている答え.だから通俗的な方法で、多くのプログラム猿(媛)が理解しなければならない知識でタイプシステムを紹介しますが、厳格性を失わないのがこの文章の意味です.
0 x 02ダイナミック(静的)タイプとは、強い(弱い)タイプ
ベース・バージョン
コンパイル時に変数タイプが静的タイプであることがわかります.実行時に変数タイプをダイナミックタイプと呼ぶことがわかります.例:
コンパイラは int age = 18; というコードをコンパイルするときにageのタイプを確定します.言い換えれば、タイプ自体が操作可能な集合を定義しているので、彼を0で割る操作はできません.しかし,C++でよく見られるauto ite = vec.iterator();のように静的タイプにも属し,これをタイプ導出と呼び,既知のタイプによってコンパイル時期に知らない変数のタイプを導出する.静的タイプ言語で変数に対してその変数タイプが許可されていない操作を行うと、構文エラーが表示されます.
しかし、var name = student.getName();のようなJavaScriptコードは動的タイプです.このコードは実行されたときにのみnameが文字列タイプであり、nullやundefinedタイプであることを知っているからです.君もタイプを導くことができない.getName関数署名には、戻り値タイプ情報は含まれません.後で、関数署名にタイプを追加する他の手段について説明します.動的タイプで変数に対してその変数タイプが許可されていない操作をすると、実行時エラーが表示されます.
暗黙変換を許可しないのは強いタイプで、暗黙変換を許可するのは弱いタイプです.例:
Pythonで'666' / 2を行うと、強いタイプの言語では暗黙的な変換が許されないため、JavaScriptで'666' / 2を行うと整数333が得られます.これは、演算を実行するときに文字列'666'が整数666に変換され、除算演算が行われるためです.
高度なバージョン
まず基本的な概念を紹介する必要があります.
プログラムエラー
  • trapped errors:プログラムの実行を終了させる(プログラムはエラーを認識し、対応するエラー処理メカニズムを使用する)、例えば0を除いてJavaの配列は
  • に境界を越えてアクセスする.
  • untrapped errors:プログラムエラー後に実行を継続する(実際には実行を継続することを保証するとは限らず、プログラム自体はエラーを知らず、対応するエラー処理メカニズムもない)、例えばC言語のバッファオーバーフロー、Jmpはエラーアドレス
  • に達する
    Forbidden Behaviors(禁止行為)
    プログラムは設計時にforbidden behaviorsのセットを定義し、すべてのuntrapped errorsを含み、trapped errorsを含む可能性があります.
    Well behaved、ill behaved
  • well behaved:プログラムの実行にforbidden behaviorsが現れない場合はwell behaved
  • と呼ぶ
  • ill behaved:forbidden behaviorsが現れる可能性がある限りill behaved
  • と呼ぶ
    彼らの関係は次の図で表すことができます.
    図から分かるように、緑のプログラムはすべてのプログラム(すべてのプログラム、あなたは考えることができて考えられない)を表し、errorはエラーのプログラムを表し、errorはtrapped errorとuntrapped errorだけを含まない.
    図に基づいて、動的タイプ、静的タイプを厳格に定義することができます.強いタイプ、弱いタイプ
  • 強タイプ:1つの言語で書かれたプログラムが赤い矩形の外部にある場合、この言語は強タイプ、すなわちwell behaved
  • である.
  • 弱いタイプ:1つの言語で書かれたプログラムが赤い矩形の内部にある可能性がある場合、この言語は弱いタイプ、すなわちill behaved
  • です.
  • 静的タイプ:1つの言語がコンパイル時に赤い矩形内に現れる可能性がある場合(構文エラーによって)を排除すると、この言語は静的タイプの
  • である.
  • 動的タイプ:実行時に赤い長方形内に発生する可能性のある言語を除外する(実行時にエラーが発生するが、弱いタイプであればuntrapped error、例えば暗黙的な変換をトリガーし、プログラムが正常に動作しているように見える)場合、この言語は動的タイプの
  • である.
    栗を挙げます.
    Pythonでtest = '666' / 3を実行すると、実行時にuntrapped errorを排除したTypeErrorエラーが発生するため、Pythonはダイナミックタイプ、強力なタイプの言語です.
    JavaScriptでvar test = '666' / 3'を実行するとtestの値が222になります.ここで暗黙的な変換が発生したため、JavaScriptは動的タイプ、弱いタイプです.さらに誇張すると[] == ![]のようなコードがJavaScriptで返されるのはtrueであり,ここでは具体的な原因である.
    Javaでint[] arr = new int[10]; arr[0] = '666' / 3;を実行すると、コンパイル中に文法エラーが発生します.これはJavaが静的タイプであることを示しています.int[] arr = new int[10]; arr[11] = 3;を実行すると、実行時に配列の境界を越えたエラー(trapped error)が発生します.これは、Javaが独自のタイプシステムを通じてuntrapped errorを排除していることを示しています.そのため、Javaは強いタイプです.
    CはJavaと似ていて、静的なタイプですが、int test[] = { 1, 2, 3 }; test[4] = 5;のようなコードC言語ではあなたの問題を発見することはできません.そのため、untrapped errorなので、Cは弱いタイプだと言います.
    次の図は、一般的な言語タイプの区分です.
    また、強いタイプの言語は通常、実行時にタイプチェックシステムを実行する必要があるため、強いタイプの言語の速度は一般的に弱いタイプよりも遅く、ダイナミックタイプも静的タイプよりも遅いため、上述した4つの言語で実行される速度はC>Java>JavaScript>Pythonであるべきである.しかし、強いタイプ、静的なタイプの言語は書くのが最も安全であることが多い.
    0 x 03ダイナミックタイプと静的タイプの違い、ダイナミックタイプをどのように利用するか
    静的タイプはコンパイル期間中に最適化されるため、一般的にパフォーマンスが高い.動的言語はタイプ操作を行う際(文字列接合、整数演算など)には、そのタイプを推測する解釈器が必要であるため、性能が低い.しかし、現代の解釈器には一般的に速度を上げるための最適化措置があり、JavaScriptのV 8解釈器を持って栗を挙げます.
    V 8の最適化プロセス(大まかなバージョン)
    Java/C++のような静的タイプ言語では、オブジェクトに対してクラステンプレートが一般的に存在することが知られています(一般的に関数を呼び出すときはクラステンプレートに行って探します).V 8のように、実行時にクラステンプレートが作成され、属性や呼び出し方法にアクセスする際にクラステンプレート内の属性のオフセットを計算するだけでよい.従来のJavaScriptオブジェクトは一般にHashまたはTrieツリーによって実現されるが,検索の効率は低い.コードの例を示します.
    function Point(x, y) { 
    this.x = x; 
    this.y = y; 
    } 
    var p1 = new Point(1, 2);

    newを使用してPoint関数を呼び出すとclass 0クラステンプレート(実行時に生成)となり、this.x = xを実行するとclass 1クラステンプレートが生成され、this.y = yを実行するとclass 2クラステンプレートが生成されます.具体的な変換過程は以下の図である.
    オブジェクトのクラステンプレートを決定すると、プロパティのアクセス速度が大幅に向上します.クラステンプレートの決定は、図のパス(変換パス)を歩くことです.オブジェクトのプロパティを追加または削除するたびに、オブジェクトのクラステンプレートが変更され、増加順序が異なる場合でも異なるクラステンプレートが生成されます.
    V 8メソッドが複数回呼び出された(同じタイプのパラメータが入力された)場合、JITを使用して関数をバイナリコードにコンパイルし、速度を上げます.
    V 8と組み合わせてまとめた最適化方案:
  • 簡単にオブジェクトを削除する属性を追加しないでください.既存の属性に対してできるだけ保証タイプが変わらないようにして、隠しクラスができるだけ多重化されることを保証します.
  • プロパティをインスタンス化するときは、できるだけプロパティの追加順序の一貫性を保証し、非表示クラスと最適化コードが
  • 多重化できることを保証する.
  • できるだけ呼び出し方法を繰り返し、伝達パラメータの個数とタイプは複数回呼び出したときに一致する
  • を維持しなければならない.
  • 配列については、push、unshiftなどの方法で配列の大きさを変更することが望ましい.緊密な配列はV 8に連続したアドレスで保存されているので、配列中の要素を勝手に削除しないでください.疎配列はV 8においてhashテーブル
  • であるからです.
  • V 8格納整数は4バイトで、大きな整数が出ると暗黙型変換に関わる性能が低下するため、32 bit
  • を超えないようにする.
    0 x 04弱い言語がもたらす問題をどのように回避するか
    弱いタイプの言語は実行時にタイプシステムが欠けているため、タイプ操作上のuntrapped errorが現れやすい.C言語では,配列アクセスの限界について前述したが,ここでは弱言語JavaScriptを例に挙げる.
  • できるだけ厳格な比較記号を使用します.例えば、===
  • 文字列を他のタイプの変数と演算する操作
  • はできるだけ行わないようにする.
  • 複雑なオブジェクトは演算子上で操作しない
  • 0 x 05言語タイプの静的スキーム
    JavaScriptのようなダイナミックなタイプの言語は静的化された後、実行時のセキュリティに対して、効率が大幅に向上するに違いない.またflowのように注釈でタイプを識別するスキームもある.
    0 x 06まとめ
    最後まで書いて、文章のタイトルがうまく取れていないことに気づいたので、そうしましょう.