Classes in typeScript and their limitations

In the traditional method, JavaScript implements the concept of classes through constructors, and implements inheritance through prototype chains. In Es6, we finally ushered in class.

In addition to implementing all the functions of classes in Es6, typeScript also adds some new usages.

class concept

Although there is a class concept in JavaScript, most JavaScript programmers may not be very familiar with classes. Here is a brief introduction to class-related concepts.

  • Class (Class) : defines the abstract characteristics of a thing, including its properties and methods
  • Object (Object) : an instance of a class,  new generated by
  • The three major characteristics of object-oriented (OOP) : encapsulation, inheritance, polymorphism
  • Encapsulation (Encapsulation) : hides the operation details of the data, and only exposes the external interface. The external caller does not need (and cannot) know the details, and can access the object through the interface provided to the outside world, and also ensures that the outside world cannot arbitrarily change the internal data of the object
  • Inheritance : The subclass inherits the parent class, and the subclass not only has all the characteristics of the parent class, but also some more specific characteristics
  • Polymorphism (Polymorphism) : Different related classes generated by inheritance can have different responses to the same method. For example  Cat , and  Dog both inherit from  Animal, but implement their own  eat methods respectively. At this time, for a certain instance, we  can directly call  the method without knowing whether it is Cat or not  ,  and the program will automatically determine how to execute it Dogeateat
  • Accessor (getter & setter) : used to change the behavior of reading and assigning properties
  • Modifiers (Modifiers) : Modifiers are keywords used to limit the properties of members or types. For example,  public to represent public properties or methods
  • Abstract Class (Abstract Class) : An abstract class is a base class for other classes to inherit, and an abstract class is not allowed to be instantiated. Abstract methods in abstract classes must be implemented in subclasses
  • Interfaces : Common properties or methods between different classes can be abstracted into an interface. Interfaces can be implemented by classes. A class can only inherit from another class, but can implement multiple interfaces

Usage of classes in TypeScript

public private 和 protected 

TypeScript can use three access modifiers (Access Modifiers), which are   and  .publicprivateprotected

  • public The modified properties or methods are public and can be accessed anywhere. By default, all properties and methods  public are
  • private The decorated property or method is private and cannot be accessed outside the class in which it is declared
  • protected The modified property or method is protected, it is  private similar to it, the difference is that it is also allowed to be accessed in subclasses

Here are some examples:

class Animal {
  public name;
  public constructor(name) {
    this.name = name;
  }
}

let a = new Animal('Jack');
console.log(a.name); // Jack
a.name = 'Tom';
console.log(a.name); // Tom

 In the example above, name it is set to  public, so direct access to instance  name properties is allowed.

Many times, we hope that some attributes cannot be directly accessed, and this time it can be used  private :

class Animal {
  private name;
  public constructor(name) {
    this.name = name;
  }
}

let a = new Animal('Jack');
console.log(a.name);
a.name = 'Tom';

// index.ts(9,13): error TS2341: Property 'name' is private and only accessible within class 'Animal'.
// index.ts(10,1): error TS2341: Property 'name' is private and only accessible within class 'Animal'.

It should be noted that in the code compiled by TypeScript, the  private external accessibility of properties is not restricted.

The compiled code for the above example is:

var Animal = (function () {
  function Animal(name) {
    this.name = name;
  }
  return Animal;
})();
var a = new Animal('Jack');
console.log(a.name);
a.name = 'Tom';

Access to  private modified properties or methods is not allowed in subclasses:

class Animal {
  private name;
  public constructor(name) {
    this.name = name;
  }
}

class Cat extends Animal {
  constructor(name) {
    super(name);
    console.log(this.name);
  }
}

// index.ts(11,17): error TS2341: Property 'name' is private and only accessible within class 'Animal'.

And if it is  protected modified, it allows access in subclasses:

class Animal {
  protected name;
  public constructor(name) {
    this.name = name;
  }
}

class Cat extends Animal {
  constructor(name) {
    super(name);
    console.log(this.name);
  }
}

When the constructor is decorated private with , the class is not allowed to be inherited or instantiated:

class Animal {
  public name;
  private constructor(name) {
    this.name = name;
  }
}
class Cat extends Animal {
  constructor(name) {
    super(name);
  }
}

let a = new Animal('Jack');

// index.ts(7,19): TS2675: Cannot extend a class 'Animal'. Class constructor is marked as private.
// index.ts(13,9): TS2673: Constructor of class 'Animal' is private and only accessible within the class declaration.

protected The class is only allowed to be inherited when the constructor is decorated with  :

class Animal {
  public name;
  protected constructor(name) {
    this.name = name;
  }
}
class Cat extends Animal {
  constructor(name) {
    super(name);
  }
}

let a = new Animal('Jack');

// index.ts(13,9): TS2674: Constructor of class 'Animal' is protected and only accessible within the class declaration.

Parameter properties

Modifiers and readonlycan also be used in constructor parameters, which is equivalent to defining the property in the class and assigning the property at the same time, making the code more concise.

class Animal {
  // public name: string;
  public constructor(public name) {
    // this.name = name;
  }
}

readonly

Read-only property keywords, only allowed in property declarations or index signatures or constructors.

class Animal {
  readonly name;
  public constructor(name) {
    this.name = name;
  }
}

let a = new Animal('Jack');
console.log(a.name); // Jack
a.name = 'Tom';

// index.ts(10,3): TS2540: Cannot assign to 'name' because it is a read-only property.

 Note that if  readonly it exists with other access modifiers, it needs to be written after it.

class Animal {
  // public readonly name;
  public constructor(public readonly name) {
    // this.name = name;
  }
}

abstract class

abstract Used to define abstract classes and their abstract methods.

What is an abstract class?

First, abstract classes are not allowed to be instantiated:

abstract class Animal {
  public name;
  public constructor(name) {
    this.name = name;
  }
  public abstract sayHi();
}

let a = new Animal('Jack');

// index.ts(9,11): error TS2511: Cannot create an instance of the abstract class 'Animal'.

In the above example, we defined an abstract class  Animaland defined an abstract method  sayHi. An error occurred while instantiating an abstract class.

Second, abstract methods in abstract classes must be implemented by subclasses:

abstract class Animal {
  public name;
  public constructor(name) {
    this.name = name;
  }
  public abstract sayHi();
}

class Cat extends Animal {
  public eat() {
    console.log(`${this.name} is eating.`);
  }
}

let cat = new Cat('Tom');

// index.ts(9,7): error TS2515: Non-abstract class 'Cat' does not implement inherited abstract member 'sayHi' from class 'Animal'.

In the above example, we defined a class  Cat that inherits the abstract class  Animal, but does not implement the abstract method  sayHi, so the compilation reports an error.

 Here is an example of using an abstract class correctly:

abstract class Animal {
  public name;
  public constructor(name) {
    this.name = name;
  }
  public abstract sayHi();
}

class Cat extends Animal {
  public sayHi() {
    console.log(`Meow, My name is ${this.name}`);
  }
}

let cat = new Cat('Tom');

In the above example, we implemented the abstract method  sayHiand the compilation passed.

It should be noted that even if it is an abstract method, this class will still exist in the compilation result of TypeScript. The compilation result of the above code is:

var __extends =
  (this && this.__extends) ||
  function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() {
      this.constructor = d;
    }
    d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new __());
  };
var Animal = (function () {
  function Animal(name) {
    this.name = name;
  }
  return Animal;
})();
var Cat = (function (_super) {
  __extends(Cat, _super);
  function Cat() {
    _super.apply(this, arguments);
  }
  Cat.prototype.sayHi = function () {
    console.log('Meow, My name is ' + this.name);
  };
  return Cat;
})(Animal);
var cat = new Cat('Tom');

class type

Adding TypeScript types to classes is easy, similar to interfaces:

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  sayHi(): string {
    return `My name is ${this.name}`;
  }
}

let a: Animal = new Animal('Jack');
console.log(a.sayHi()); // My name is Jack

 

Guess you like

Origin blog.csdn.net/qq_57423665/article/details/130714117