Type Scriptの中のprvate、protected

5887 ワード

まず、privateprotectedの現段階は、キーワードではなく、javascriptの中の予約ワード(Reserved words)だけであることを確認したい.したがって、Keywords の中の純粋なタイプのステートメント文は、コンパイル後に消去されます.
class Person {
  public name: string;
  protected age: number; 
  private isMarried: boolean;
}
//    
class Person {
}
Type Scriptは構造言語です.2つの異なるタイプを比較する場合、どちらから来ても、すべてのメンバーのタイプが互換性がある場合、これらのタイプ自体は互換性があるということになる.
interface Named {
  name: string;
}

class Bar {
  name: string;
}

class Foo {
  name: string;
}

// OK, because of structural typing
let a: Named = new Person(); //✔️
let b: Foo = new Bar(); //✔️
TypeScript属性宣言のデフォルトはTypeScript であるので、上記はpublic形式でアクセスでき、b.nameはデフォルトはjavaである.
しかし、protectedのメンバーまたはprivateのメンバーのタイプを比較すると、これらのタイプは区別される.このうちの1つのタイプがprvateのメンバーを有する場合、他のタイプは、同一の声明に由来するprvateのメンバーを持たなければならない.これはprotectedメンバーにも適用されます.
class Bar {
  private name: string;
}

class Foo {
  private name: string;
}

let bar: Bar = new Foo(); // ❌ 
//Type 'Foo' is not assignable to type 'Bar'.
  //Types have separate declarations of a private property 'name'.
上記の概念ルールはType Script Handbookから由来しています.ここでは単なる前置きをするだけです.protectedは、タイプ互換性を判断する際に、なぜ処理TypeScriptprivateの規則がprotectedとは異なるのか、という潜在的な利点があるのか.
電気自動車はまだ発展の初期段階にあると仮定して、自動車ブランドテスラ、蔚来の最大走行距離数はpublic値と同じです.
interface Car {
  maxMileage: number;
}

class Tesla implements Car {
   maxMileage: number = 500;
}

class Nio implements Car {
   maxMileage: number = 500;
}

function drive(car :Tesla) {
   console.log(car.maxMileage)
}

let tesla = new Tesla();
let nio = new Nio();
drive(tesla); // ✔️
drive(nio); // ✔️
maxMileageは構造言語であるため、TypeScriptTeslaはまた同じ名前、タイプのフィールドNioを持っているので、maxMileageが入力された宣言がdriveタイプであっても、チェックすることができる.現在は誤用しても、Teslaの表現は同じです.問題はありませんが、技術の発展につれて、2つのブランドのdriveの値は違っています.maxMileageの行為も千差万別です.このバグは深刻な故障を引き起こすまでずっと潜伏しています.
上記の例に基づいて、1を追加した)2つの場所において、drive(private)宣言のprotected属性が多くなり、構造のように解決されたが、またタイプのシーンを区別して、同様のタイプのシステムの効果を達成したい.ここでは、brandprivate属性を利用して、同じ宣言から派生しなければ、タイプ互換性を判定できない.
class Tesla implements Car {
   private brand: string = "Tesla"; // 1)
   maxMileage: number = 500;
}

class Nio implements Car {
   private brand: string = "Tesla";  //2)
   maxMileage: number = 500;
}

function drive(car :Tesla) {
   console.log(car.maxMileage)
}
let tesla = new Tesla();
let nio = new Nio();
drive(tesla); // ✔️
drive(nio); // ❌
//Argument of type 'Nio' is not assignable to parameter of type 'Tesla'.
  //Types have separate declarations of a private property 'brand'.

//   
class Tesla {
    constructor() {
        this.brand = "Tesla";
        this.maxMileage = 500;
    }
}
class Nio {
    constructor() {
        this.brand = "Tesla";
        this.maxMileage = 500;
    }
}
私たちが望む効果を達成しましたが、クラス例はprotected属性が多くなり、実行時のオーバーヘッドが増加しました.これはあなたが望むものではないなら、次のように処理できます.
class Tesla implements Car {
  //@ts-ignore
   private brand: string;
   maxMileage: number = 500;
}

class Nio implements Car {
   //@ts-ignore
   private brand: string ;
   maxMileage: number = 500;
}

//   
class Tesla {
    constructor() {
        this.maxMileage = 500;
    }
}
class Nio {
    constructor() {
        this.maxMileage = 500;
    }
}
コンパイルしたコードがとてもきれいに見えます.brandは、初期化されていない属性によってエラーがコンパイルされることを避けるために、 //@ts-ignore だけで必要である.strictPropertyInitialization: trueエラーはまた類extends継承の時に現れます.初めて見ると変ですが、フォームは違っていますが、エラーメッセージは似ています.
class ElectricVehicle {
   private charge() {};
}

//Type 'FF91' is not assignable to type 'ElectricVehicle'.
 // Types have separate declarations of a private property 'charge'
class FF91 extends ElectricVehicle {   // ❌
    private charge() {};
}
Types have separate declarations of a private property privateに変更することにより、修復することができる.多くの文章では、これはprotected publicが意味的に私有であるため、サブクラスが見えないので、カバーすることはできないが、privateprotectedは、語義的にはサブクラスに対して可視であり、サブクラスは現在カバー行為を行っていることを知っている.publicは、上記のクラスのステートメントをコンパイルすることによって、TypeScript方法をカバーすることができると仮定する.しかし、次の文を実行すると、上記のエラーが再び発生します.
let parent = new ElectricVehicle();
let child = new FF91();
parent = child; // ❌
//Type 'FF91' is not assignable to type 'ElectricVehicle'.
 // Types have separate declarations of a private property 'charge'
最初の例では、privateは、2つの構造が類似しているクラスだけであり、相続関係はなく、タイプが互換性がないと判定することも理解できる.ここでは親子のタイプが互換性がないと自円できません.コンパイラは事前にクラス声明の時にエラーを報告して、使用段階に遅れないようにします.これはまた、なぜFoo、Barクラスの声明の継承時のエラーメッセージが前のものと同じですか?
例Playground