object-oriented

TypeScript is object-oriented programming.

What is object orientation?

In short, all operations in a program are done through objects. Computer programs are essentially abstractions of real things. A person, a car, a dog, these are objects, and the actions that these objects emit are methods of the object, and certain features are properties of the object. For example, a person, his height, appearance, name, age and so on are his attributes in the object, and his actions, walking, running, talking and so on are his methods in the object.

class

What is a class?

A class is a model of an object from which objects can be created. The properties and methods of an object are explicitly expressed in a class.

Let’s define a simple class:

class Person {
  name: string = 'xiaobai';
  static age: number = 18;
  say() {
    console.log('hello');
  }
  static run() {
    console.log('run'); }}let person = new Person()
Copy the code

This defines a simple class that is instantiated as an object using the new keyword. Person is the instance object.

Static refers to a static property of a class that is accessed by the class name without creating an object, such as Person.age. But the instance object cannot be accessed. Static methods are used in the same way as static properties.

Class constructor

Why do we need it?

When we create a class, it is usually not possible to instantiate only one object, it is often possible to instantiate multiple objects.

// Create instance objects with the same property values and methods
class Person {
  name: string = 'xiaobai';
  say() {
    console.log('hello'); }}let person = new Person()
Copy the code

Constructor This constructor is executed immediately each time a new instantiates an object.

class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
    console.log(this);  // It points to the instantiated object per}}let per1 = new Person('xiaobai1');
let per2 = new Person('xiaobai2');
let per3 = new Person('xiaobai3');
Copy the code

After each instantiation of the object, the constructor function generates a this that points to the object created by the instantiation.

Adding a property by this.name is equivalent to adding a property to the instantiated object. And then we’ll bring in the parameters that we passed when we instantiated, and we’ll create objects with different property values. Method, which refers to whichever instance object calls the method.

Class extends

class Dog {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log('wang wang'); }}class Cat {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log('meow meow'); }}Copy the code

We create a Dog class and a Cat class, and we see that they all have the same properties and methods. We repeat the code twice. If we create a cow, a snake, a pig, and so on, we start repeating the same work.

So we use inheritance to simplify it:

class Animal {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log('call'); }}class Dog extends Animal {
  run() {
    console.log(`The ${this.name}In the run `);
  }
  // Override the parent method
  say() {
    console.log('wang wang')}}class Cat extends Animal {
  // Override the parent method
  say() {
    console.log('meow meow')}}let dog = new Dog('white'.3);
console.log(dog);      // {name: "小白", age: 3}
dog.say();  / / wang wang
let cat = new Cat('black'.2);
console.log(cat);      // {name: "black ", age: 2}
dog.say();  / / meow meow
Copy the code

Can be seen from the above code, we use the extends keyword to inherit the Animal of this class, so that the Dog, Cat, these two classes have the Animal on the class of methods. This greatly simplifies the amount of code we need to write without reinventing the wheel.

An inherited subclass not only has a method that has a parent class, but it can also have its own methods, such as the run method in the Dog subclass.

If an inherited subclass adds the same method as the parent class, the subclass’s method overrides the parent class’s method. The subclass method overrides the method of the parent class and is calledMethod rewriting.

The super keyword

Start with some code:

class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  say() {
    console.log('call'); }}class Dog extends Animal {
  age: number;
  constructor(name: string, age: number) {
    super(name);   // Call the parent constructor
    this.age = age;
  }
  say() {
    super.say()    // Call the method of the parent class}}let dog = new Dog('white'.3);
console.log(dog);
Copy the code

Use super in subclass methods to represent the parent class of the current class.

Add new attributes to a subclass. If a new constructor is written in a subclass, the subclass constructor must call the superclass constructor.

An abstract class

Sometimes we don’t need a superclass to instantiate and create an object. A superclass is a superclass that holds only common properties and methods for inheritance. This is where abstract classes are used, which can only be inherited, not instantiated.

abstract class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  abstract say(): void;
}
class Dog extends Animal {
  say() {
    console.log('call'); }}Copy the code

In the Abstract abstract class, an abstract method can be defined, and subclasses must override the abstract method. Abstract methods begin with abstract and have no method body. In an abstract class, you don’t have to write abstract methods.

Class modifier

Class modifiers have three public private protected

public

Public properties, decorated properties that can be accessed (modified) from anywhere, including inherited subclasses

Property defaults to public if no modifier is set before it

class Person {
  public name: string;
  public age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age; }}let person = new Person(Sun Wukong.18);
console.log(person);    {name: "Sun Wukong ", age: 18}
person.name = 'Pig Eight Quit';
person.age = 20;
console.log(person);    {name: "pig ", age: 20}
Copy the code

We can see that public decorates the property:

Properties can be modified at will in the instantiated object, making the data in the object very insecure.

private

Private property that can only be accessed (modified) inside the class

Change the name property of the Person class to a private property and the result is as follows:

class Person {
  private name: string;
  public age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age; }}let person = new Person(Sun Wukong.18);
console.log(person);    {name: "Sun Wukong ", age: 18}
person.name = 'Pig Eight Quit';  // An error is thrown, "Property 'name' is private and can only be accessed in the Person class"
Copy the code

If the attributes are privatized and cannot be accessed externally, we can add methods to the class to access (modify) the attributes as follows:

class Person {
  private name: string;
  public age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  getName () {
    return this.name;
  }

  setName (value: string) {
    this.name = value; }}let person = new Person(Sun Wukong.18);
person.setName('Pig Eight Quit');
console.log(person.getName());   // Print 'pig eight Quit'
Copy the code

The name private property can be changed inside the object by setting the setName method.

You can also use the getters and setters provided by TS as follows:

class Person {
  private name: string;
  public age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  get _name() {
    return this.name;
  }

  set _name(value: string) {
    this.name = value; }}let person = new Person(Sun Wukong.18);
person._name = 'Pig Eight Quit';
console.log(person._name);   // 'pig eight Quit'
Copy the code

withprivateYou can encapsulate a property, you don’t access its property directly, you access it through getter, setter methods.

protected

Protected properties that can only be used (modified) in the current class and subclasses and cannot be accessed in the instantiated object.

interface

Interface implementation object

Interfaces are used to define a class structure, which properties and methods should be in a class, and can also be used as type declarations.

Here’s an example:

interface User {
  name: string;
  age: number;
}

interface User {
  gender: string;
}

const USER1: User = {
  name: 'Ming'.age: 18.gender: 'male'
}

console.log(USER1);
Copy the code

We define an interface of the user object. The first interface contains the name and number attributes, and the second interface contains the gender attributes. We can see that the two interfaces can be declared repeatedly, and the attribute detection in the two interfaces will be merged. You have to have a name, age, gender.

Interface implementation class

Interfaces can limit class deconstruction when defining classes

Interface definition class features:

  • None of the attributes in the interface can have actual values
  • The interface defines only the structure of the object, regardless of the actual value
  • All methods in the interface are abstract methods

When you define a class, you can make it implement an interface. To implement an interface is to make the class meet the requirements of the interface

/** * interface implementation class */
interface user {
  name: string;
  say(): void;
}

class user1 implements user {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  say() {
    console.log('hello'); }}Copy the code

As you can see, interfaces are a lot like abstract classes, but with significant differences:

  • Methods in the interface are abstract and cannot have actual values. Abstract methods can have abstract methods as well as ordinary methods
  • When you use interfaces, you use the implements keyword, and when you use abstract classes, you use extends inheritance

In essence, both define a standard for a class that implements an interface, or inherits abstract methods, and must conform to that standard.

The generic

When defining functions or classes, you can use generics if the type is ambiguous.

When we do not know what type the function argument is, we often use any to indicate any type. However, using any turns off type detection for TS, so we use generics instead.

Here’s a simple code example:

// Use any to turn off type detection
function fn(a: any) :any {
   return a;
}

// Use generics to automatically determine the type
function fn<T> (a: T) :T {
  return a;
}
fn<string> ('hello');  // You can also specify the type when called
Copy the code

Class uses generics:

class User<T> {
  name: T;
  constructor(name: T) {
    this.name = name; }}let user = new User<string> ('zhangsan');
Copy the code