Inheritance

  1. Inheritance

    Inheritance is used to create subclasses of a class. The subclass has the properties and methods of the parent class, and also has the exclusive properties and methods of the subclass.

    The keyword for inheritance is extends. Subclasses can only inherit from one parent class, which is different from interface’s implement.


  2. Constructor of subclass

    1. If the subclass does not write a constructor, the subclass inherits the constructor of the parent class. The incoming parameters and corresponding properties are exactly the same as those of the parent class.

      1
      2
      3
      4
      class Department {
      constructor(private name: string, private id: string) {}
      }
      class ITDepartment extends Department {}

    2. Subclasses have their own constructors

      When adding your own constructor in a subclass, you must add super() in the subclass. super() accepts the parameters of the parent class constructor.

      In the constructor, super() should be used before other code.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      class Department {
      constructor(private id: string, private name: string) {}
      }
      class ITDepartment extends Department {
      constructor(private id: string) {
      super(id, "IT"); //super receives the parameters of the parent class constructor. The first parameter is a variable, and the second parameter is hard-coded by the subclass itself.
      }
      }
      const accounting = new ITDepartment("d1");

      Subclasses can also add new parameters to the constructor.

      1
      2
      3
      4
      5
      class ITDepartment extends Department {
      constructor(private id: string, public admins: string[]) { //Add new parameters
      super(id, "IT");
      }
      }

  3. protected modifier

    Private properties are actually only accessible from within the class in which they are defined, not from within inherited subclasses. For example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Department {
    private employees: string[] = []; //private
    constructor(private id: string, private name: string) {}
    }
    class ITDepartment extends Department {
    constructor(private id: string) {
    super(id, "IT");
    }
    addEmployee(name: string){
    this.employees.push(name); //Cannot be added at this time because the employees attribute is private.
    }
    }
    const accounting = new ITDepartment("d1");
    accounting.addEmployee("derek"); //Cannot be added at this time because the employees attribute is private.

    At this point we need to use the protected modifier. It ensures that the modified properties/methods are available not only within the class, but also in any class that extends the class.


  4. getter and setter

    getter and setter are get and set keywords. They are to give the outside world a way to assign and obtain values in the class, and they can also add logic, such as judgment, etc. before assignment and value acquisition. The getter must return a value.

    What should be noted here is that although the properties of getters and setters are declared with (), they are not used with (). This means that the setter and getter are not executed as a method, but are only accessed as a property.

    Getters and setters share property names. Externally, whether it is a getter or a setter will be automatically determined based on assignment or value acquisition.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Person {
    private _age: number; //_age, different from age() below

    get age(): number {
    return this._age;
    }

    set age(newAge: number) {
    if (newAge < 0) {
    throw new Error("Age cannot be negative.");
    }
    this._age = newAge;
    }
    }

    const person = new Person();
    person.age = -30; // set age (will throw an error) Note that there is no ()
    console.log(person.age); // get age (will not be executed due to the error) Note that there is no ()

  5. static static methods and properties

    The static keyword is used to define static members of a class, which are members that belong to the class itself rather than to instances of the class. **Static members can be methods or properties.

    A static method is a method that is called directly without relying on an instance of a class. Static methods can access static properties and other static methods, but not instance properties or instance methods. In TS, static methods are defined using the static keyword, for example:

    1
    2
    3
    4
    5
    6
    7
    class MyClass {
    static myStaticMethod() {
    console.log("This is a static method.");
    }
    }

    MyClass.myStaticMethod();

    It should be noted that static members cannot be accessed by instantiated objects, only through the class itself.

    Static members cannot be accessed by non-static members in the class. For example, this.static member in the constructor will report an error. This is because they refer to an instance created based on the class, and static properties are not available on instances. Static members are detached from the instance. If you need to access a static member from a non-static member, you need to replace this with the class name:

    1
    2
    3
    4
    5
    6
    7
    class Department {
    static fiscalYear = 2020;
    private employees: string[] = [];
    constructor(private id: string, private name: string) {
    console.log(Department.fiscalYear); //Class name. Static member
    }
    }

  6. abstract abstract class

    An abstract class is a class defined using the abstract keyword. Abstract classes cannot be instantiated, but can only be inherited. Abstract classes are used to force all derived classes to share some common properties and methods without providing specific values in the base class.

    Abstract classes can contain abstract methods and non-abstract methods. Abstract methods are methods that have no implementation (that is, there is no {} part in the method) and they must be implemented in a derived class. Non-abstract methods are implemented methods, and derived classes can choose whether to override them. A derived class must implement all abstract methods, otherwise it must itself be an abstract class.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    abstract class Animal {
    abstract makeSound(): void; //Abstract method, no {}
    move(): void { console.log("Moving..."); } //Non-abstract method
    }

    class Cat extends Animal { // Derived class
    makeSound(): void { console.log("Meow!"); }
    }

    const cat = new Cat();
    cat.makeSound(); // "Meow!"
    cat.move(); // "Moving..."

    In the example, Animal is an abstract class, which contains an abstract method makeSound and a non-abstract method move. Cat inherits Animal and implements the makeSound method. Note that the move method is not overridden in Cat, so it inherits the implementation in Animal.

    The main function of abstract classes is to define some common functions and stipulate that subclasses must implement certain methods, thereby improving code reusability and maintainability.


  7. singleton mode and private constructor private constructor

    The Singleton (single case) pattern is to ensure that there is always only one instance of a class and provide a global access point to obtain the instance.

    Implementations of the Singleton pattern usually include a private constructor, a static method to obtain the singleton instance, and a static property to save the singleton instance. Singleton instances can only be created once and are managed in static methods. When you need to use a singleton instance, just call the static method.

    private constructor refers to a constructor that can only be called inside the class. Private constructors are often used to implement patterns such as singleton pattern or factory pattern. Private constructors cannot be called outside the class to create instances of the class, they can only be used inside the class (i.e. ensuring that we cannot call new).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Singleton {
    private static instance: Singleton;

    private constructor() {
    // ...
    }

    public static getInstance(): Singleton {
    if (!Singleton.instance) {
    Singleton.instance = new Singleton();
    }
    return Singleton.instance;
    }
    }

    const singleton1 = Singleton.getInstance();
    const singleton2 = Singleton.getInstance();
    console.log(singleton1 === singleton2); // true

Share