継承


n/a.ターゲット

  • 225章の内容を理解し、まとめます.
  • 25.クラス-継承(extends)


    ※本文の目次は本の目次とは異なります.

    25-8. 継承クラスと継承コンストラクション関数

  • クラスベースの継承は、既存のクラスを継承することによって新しいクラスを拡張(extends)することによって定義される.
  • クラスとコンストラクション関数は、インスタンスを生成できる関数です.これは似ていますが、クラスは既存のクラスを継承して拡張する構文を提供しますが、コンストラクション関数は提供しません.
  • class Animal {
      constructor(age, weight) {
        this.age = age;
        this.weight = weight;
      }
      
      move() { return "move"; }
    }
    
    // 상속
    class Lion extends Animal {
      hunt() { return "hunt"; }
    }
    
    const lion = new Lion(4, 21);
    
    console.log(lion instanceof Lion);
    console.log(lion instanceof Animal);
    
    console.log(lion.move());
    console.log(lion.hunt());
    
    // 결과
    true
    true
    "move"
    "hunt"

    25-9. extendsキーワード

    class Animal {}
    
    // 상속
    class Lion extends Animal {}
  • で拡張クラスを継承するには、extendsキーワードで定義します.
  • によって継承拡張されたクラスをサブクラス(上のコードではLion)またはサブクラスと呼ぶ.
  • サブクラスに継承されるクラスをスーパークラス(上のコードではAnimal)または親クラスと呼びます.
  • function Animal(age) {
      this.age = age;
    }
    
    class Lion extends Animal {}
    const lion = new Lion(7);
    console.log(lion.age);
    
    // 결과
    7
  • はまた、extendsキーワードを使用してクラスおよびコンストラクション関数を継承することもできる.
  • セグメント、extendsキーワードの前にクラスが必要です.
  • 25-10. ダイナミック継承

    // 생성자 함수
    function Animal() {}
    
    // 클래스
    class Plant {}
    
    let flag = true;
    class Lion extends (flag ? Animal : Plant) {}
    
    flag = false;
    class Tree extends (flag ? Animal : Plant) {}
    
    const lion = new Lion();
    const tree = new Tree();
    
    console.log(lion instanceof Animal);
    console.log(lion instanceof Plant);
    console.log(tree instanceof Animal);
    console.log(tree instanceof Plant);
    
    // 결과
    true
    false 
    false
    true
  • extendsキーワードの後、クラスや3つの演算子などの式を使用して、継承するオブジェクトを動的に決定できます.
  • 25-11. サブクラスのconstructor


    コンストラクション関数を省略すると、
  • クラスはデフォルトでコンストラクション関数を定義します.
  • class Animal {}
    class Animal {
      // 암묵적으로 정의
      constructor() {}
    }
  • と同様に、コンストラクション関数を省略すると、サブクラスも暗黙的に定義されます.
  • class Animal {}
    
    class Monkey extends Animal {}
    class Animal {
      // 암묵적으로 정의
      constructor() {}
    }
    
    class Monkey extends Animal {
      // 암묵적으로 정의
      constructor(...agrs) {
        super(...args);
      }
    }
    スーパークラスとは異なり、
  • サブクラスはagrsというパラメータとともに定義される.
  • agrsは、new演算子とともにクラスを呼び出すときに渡されるパラメータのリストです.
  • super()は、スーパークラスの構造関数()を呼び出すことによってインスタンスを生成する.
  • Restパラメータ

  • パラメータで...加算するとrestパラメータとなり、関数に渡されるパラメータリストが順番に渡されます.
  • 25-12. スーパーキー

  • スーパーキーワードには、次の機能があります.
  • 関数のようにスーパークラスのコンストラクション関数(constructor)を呼び出す.
  • superを参照すると、スーパークラスメソッドを呼び出すことができる.
  • 25-12-1. スーパーコール

    class Animal {
      constructor(a, b) {
        this.a = a;
        this.b = b;
      }
    }
    
    class Monkey extends Animal {
      constructor(a, b, c) {
        super(a, b);
        this.c = c;
      }
    }
    
    const monkey = new Monkey(1, 2, 3);
    console.log(monkey);
    
    // 결과
    Monkey {a: 1, b: 2, c: 3}
  • new演算子によってクラスが呼び出されると、渡されたパラメータ1,2,3がMonkeyクラスのコンストラクション関数に渡される.
  • 以降、superを呼び出してAnimalクラスのコンストラクタに一部を渡す.
  • のように、インスタンス初期化のために渡されたパラメータはスーパークラスとサブクラスに割り当てられ、関係を継承する2つのクラスが互いに協力してインスタンスを生成する.
  • 段、superを呼ぶときに注意事項があります.
  • サブクラスでコンストラクション関数を省略しない場合、コンストラクション関数を定義するときにsuperを呼び出す必要があります.
  • class Animal {}
    
    class Rabbit extends Animal {
      constructor() {}    // Error
    }
    
    const rabbit = new Rabbit();
    
    // 결과
    "Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor"
  • サブクラスのコンストラクション関数でsuperを呼び出すまでは、参照できません.
  • class Animal {}
    
    class Rabbit extends Animal {
      constructor(a) {
        this.a = a;    // Error
        super();
      }
    }
    
    const rabbit = new Rabbit(1);
    
    // 결과
    "ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor"
  • superは、サブクラスのコンストラクション関数のみで呼び出される必要があります.
  • class Animal {
      constructor() {
        super();    // Error
      }
    }
    
    class Rabbit extends Animal {
      constructor(a) {
        super();
      }
    }
    
    const rabbit = new Rabbit(1);
    
    // 결과
    "Uncaught SyntaxError: 'super' keyword unexpected here"

    25-12-2. スーパーリファレンス

  • メソッド内でsuperを参照する場合、スーパークラスメソッドを呼び出すことができます.
  • サブクラスのプロトタイプメソッドでは、superを使用してスーパークラスのプロトタイプメソッドを参照できます.
  • class Parent {
      constructor(job1, job2) {
        this.mom = job1;
        this.dad = job2;
      }
      
      getParentJob() {
        return `mom is ${this.mom} and dad is ${this.dad}`
      }
    }
    
    class Child extends Parent {
      constructor(name, age1, age2) {
        super(age1, age2);
        this.name = name;
      }
      
      getParentJob() {
        return `${this.name}'s ${super.getParentJob()}`
      }
    }
    
    const james = new Child("james", "reporter", "programmer");
    console.log(james.getParentJob());
    
    // 결과
    "james's mom is reporter and dad is programmer"
  • サブクラスの静的メソッドでは、superがスーパークラスの静的メソッドを参照することができる.
  • class Animal {
      static type() {
        return "is Animal";
      }
    }
    
    class Tiger extends Animal {
      static type() {
        return `tiger ${super.type()}`
      }
    }
    
    console.log(Tiger.type());
    
    // 결과
    "tiger is Animal"

    25-13. 継承クラスのインスタンス作成プロセス

  • 長方形をRectangleクラスとして抽象化し、次のように色拡張を追加するColorRectangleクラスを継承して定義します.
  • // 수퍼클래스
    class Rectangle {
      constructor(width, height) {
        this.width = width;
        this.height = height;
      }
      
      getArea() {
        return this.width * this.height;
      }
      
      toString() {
        return `width = ${this.width}, height = ${this.height}`;
      }
    }
    
    // 서브클래스
    class ColorRectangle extends Rectangle {
      constructor(width, height, color) {
        super(width, height);
        this.color = color;
      }
      
      toString() {
        return super.toString() + `, color = ${this.color}`;
      }
    }
    
    const colorRectangle = new ColorRectangle(2, 4, "red");
    console.log(colorRectangle);
    console.log(colorRectangle.getArea());
    console.log(colorRectangle.toString());
    
    // 결과
    ColorRectangle {width: 2, height: 4, color: 'red'}
    8
    "width = 2, height = 4, color = red"
  • サブクラスColorRectangleがnew演算子とともに呼び出された場合、次の手順でインスタンスが作成されます.
  • サブクラスのスーパーコール
  • スーパークラスインスタンスを作成し、
  • をバインドします.
  • スーパークラスインスタンス初期化
  • サブクラス構築関数を返し、
  • をバインドします.
  • サブクラスのインスタンス初期化
  • は、
  • インスタンス
  • を返します.

    25-13-1. サブクラスのスーパーコール


    new演算子とともに呼び出されると、
  • 2クラスを継承しないは暗黙的に空のオブジェクトを作成し、このオブジェクトにバインドします.
  • ただし、サブクラスは自分でインスタンスを作成するのではなく、スーパークラスにインスタンスの作成を委任します.したがって、サブクラスのコンストラクション関数はsuperを呼び出す必要があります.呼ばないとエラーになります.
  • スーパーキーが関数のように呼び出されると、スーパークラスのコンストラクション関数が呼び出されます.
  • 25-13-2. スーパークラスインスタンスを作成し、このインスタンスをバインド

  • スーパークラスのコンストラクション関数が実行される前に、空のオブジェクトが作成され、バインドされます.
  • スーパークラスの構造関数の内部で、これは生成されたインスタンスを指す.すなわち、インスタンスはスーパークラスを指しますが、new演算子とともに呼び出されるサブクラスです.
  • プロトコルタイプの観点から、生成されたインスタンスのプロトコルタイプは、スーパークラスのプロトタイププロトコルが指すオブジェクトRectangleではなく、サブクラスのプロトタイププロトコルが指すオブジェクトColorRectangleである.
  • class Rectangle {
      console.log(this);		// ColorRectangle {}
      
      // 생략
    }
    
    class ColorRectangle extends Rectangle {}
    
    const colorRectangle = new ColorRectangle(2, 4, "red");

    25-13-3. スーパークラスのインスタンスの初期化

  • インスタンスが作成され、バインドされている場合は、初期化が行われます.
  • は、これにバインドされたインスタンスにpropertyを追加し、パラメータ伝達の初期値としてコンストラクション関数を使用してインスタンスのpropertyを初期化する.
  • class Rectangle {
      constructor(width, height) {
        this.width = width;
        this.height = height;
        
        console.log(this); 		// ColorRectangel {width: 2, height: 4}
      }
    }
    
    class ColorRectangle extends Rectangle {}
    
    const colorRectangle = new ColorRectangle(2, 4, "red");

    25-13-4. サブクラスコンストラクション関数を返してバインド

  • スーパークラスの初期化操作が完了すると、スーパーコールが終了し、制御フローはサブクラス構築関数に戻る.
  • の場合、superが返すインスタンスはこれにバインドされます.
  • サブクラスは、個別のインスタンスを作成するのではなく、スーパーリターンインスタンスをインスタンスにバインドして使用します.
  • class ColorRectangle extends Rectangle {
      constructor(width, hieght, color) {
        console.log(this);		// Error
        super(width, height);
        console.log(this);		// ColorRectangel {width: 2, height: 4}
      }
    }
    
    const colorRectangle = new ColorRectangle(2, 4, "red");
  • に示すように、superが呼び出されていない場合、インスタンスは作成されず、このインスタンスにバインドされません.
  • サブクラスのコンストラクション関数がsueprを呼び出す前に参照できない理由です.
  • 25-13-5. 初期化サブクラスインスタンス


    このインスタンスにバインドされたインスタンスにpropertyを追加し、パラメータ伝達の初期値としてコンストラクション関数を使用してpropertyを初期化します.
    class ColorRectangle extends Rectangle {
      constructor(width, hieght, color) {
        super(width, height);
        this.color = color;
      }
    }

    25-13-6. インスタンスを返す

  • で完了したインスタンスによってバインドされたthisはデフォルトで返されます.
  • class ColorRectangle extends Rectangle {
      constructor(width, hieght, color) {
        super(width, height);
        console.log(this);	// ColorRectangel {width: 2, height: 4}
        this.color = color;
        console.log(this);	// ColorRectangel {width: 2, height: 4, color: "red"}
        
        // return this;
      }
    }
    
    const colorRectangle = new ColorRectangle(2, 4, "red");

    25-14. 標準ビルダー関数の展開

  • extendsキーワードは、String、Number、Arrayなどの標準バージョンのオブジェクトを拡張することもできます.
  • class MyArray extends Array {
      uniq() {
        return this.filter((v, i, self) => self.indexOf(v) === i);
      }
      
      average() {
        return this.reduce((pre, cur) => pre + cur, 0) / this.length;
      }
    }
    
    const myArray = new MyArray(1, 1, 2, 3);
    console.log(myArray.uniq());
    console.log(myArray.average());
    
    // 결과
    MyArray(3) [1, 2, 3]
    1.75
  • Arrayジェネレータ関数を継承し、MyArrayクラス生成を拡張する例はArrayである.PrototypeとMyArrayPrototypeのすべてのメソッドを使用できます.
  • 注意が必要なのはArrayです.Prototypeメソッドmapまたはfilterを使用しても、ArrayクラスインスタンスではなくMyArrayクラスインスタンスが返されます.
  • console.log(myArray.filter(v => v % 2).uniq().average());
  • フィルタを使用するとMyArrayクラスも返されるため、uniqメソッドとaverageメソッドを連続的に呼び出すことができます.