Classes of TypeScript -- ts

Classes of TS

In traditional JavaScript, we use constructors to implement the concept of classes and inheritance through prototype chains. It's worth celebrating that we finally waited for ES6 and ushered in the class keyword. Front-end engineers familiar with ES6 are certainly familiar with this keyword. In TS, this part has been expanded and many new things have been added.

Class Definition

We use the class keyword to define a class, and we can add attributes and methods to the class.

class Person {
    name: string
    age: number

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    sayHello() {
        console.log(`Hello, I am ${this.name}, ${this.age} years old.`);
    }
}

const p1 = new Person("xiaoming", 21);
p1.sayHello();

In the above code, we define a Person class, which has two attributes of name, age, constructor and sayHello. We generated an object p1 through new Person(...), and we called the sayHello method to print personal information.
This is a simple class that shows us the basic use of classes in TS.

Class Inheritance

In ES6, we use the extends keyword to achieve inheritance. In TS, we do the same.

class Person {
    name: string
    age: number

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    sayHello() {
        console.log(`Hello, I am ${this.name}, ${this.age} years old.`);
    }
}

class Student extends Person {
    stuId: string

    constructor(name: string, age: number, stuId: string) {
        super(name, age);
        this.stuId = stuId;
    }
    sayHello() {
        super.sayHello();
        console.log("I am a student!");
    }
}

const s1 = new Student("xiaoming", 21, "W12138");
s1.sayHello();

On the basis of the Person class I just implemented the Student class through inheritance and added a new attribute stuId.
In the Student constructor, use super(... ) Calling the constructor of the parent class, we also override the sayHello method in the Student class, which calls the sayHello of the parent class through super.sayHello().
We use inheritance to improve the utilization of code. We don't need to repeat some redundant code. It plays an important role in the design pattern.

Access modifier

Access modifiers are not available in JavaScript, so let's go into detail.
In TS, there are three access modifiers, protected private public

  • The attributes or methods modified by public are public and can be accessed anywhere. By default, all attributes and methods are public.
  • Private-modified attributes or methods are private and cannot be accessed externally from classes declaring them
  • Protected modifies attributes or methods that are protected, similar to private, except that they are also accessible in subclasses.

public
Let's start with the simplest public

class Person {
    public name: string
    public age: number

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    sayHello() {
        console.log(`Hello, I am ${this.name}, ${this.age} years old.`);
    }
}

I added the public access attribute keyword to the name and age attribute, which is also the default value.
public name: string and name: string equivalence

const p1 = new Person("cyl",  21);
console.log(p1.name);

Because the access attribute of name and age is public, we can access it directly through the instance. attribute name outside.
Now think about the previous code. Why can we use p1.sayhello, new Person()? You must have thought of it, smart man! ____________ That's because the access properties of sayHello and constructor are public.

private
private Private, the hero of a mobile game (Lub + Skin Features) has roughly the following lines:

Mink cicada private variables, who dare to visit, come to see.

class Person {
    private name: string
    public age: number

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    sayHello() {
        console.log(`Hello, I am ${this.name}, ${this.age} years old.`);
    }
}

const p1 = new Person("cyl",  21);
console.log(p1.name);

We change the access attribute of name to private, so when we access the name attribute outside

It's very clear that access is only allowed in Person, and its subclasses are not good, let alone external ones.

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

If we add private access attributes to the constructor, can we still generate instances outside through the new operator?

Not really.

protected
Protected, like private, is also designed to restrict user access, but protected requires less access and subclasses can be accessed.

class Person {
    name: string
    age: number

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    protected sayHello() {
        console.log(`Hello, I am ${this.name}, ${this.age} years old.`);
    }
}

class Student extends Person {
    stuId: string

    constructor(name: string, age: number, stuId: string) {
        super(name, age);
        this.stuId = stuId;
    }
    sayHello() {
        super.sayHello();
        console.log("I am a student!");
    }
}

const s1 = new Student("xiaoming", 21, "W12138");
s1.sayHello();

const p1 = new Person("cyl",  21);
p1.sayHello();

We added protected access property to the sayHello method in the Person class and used the sayHello method of the parent class to rewrite the sayHello method in the Student class. That's OK, but we made a mistake when calling the sayHello method through the new Person(...) generation instance.

Accessor

TS's access is similar to JS's use of Object.defineProperty to set setter and getter. When users need additional processing for assignment and valuation of object attributes, they can use accessors.

class Person {
    firstName: string
    lastName: string
    private _fulllName: string

    constructor(fn: string, ln: string) {
        this.firstName = fn;
        this.lastName = ln;
    }
    get fullName () {
        this._fulllName = this.firstName + this.lastName;
        return this._fulllName;
    }
    set fullName (name: string) {
        let arr: string[] = name.split(" ");
        this.firstName = arr[0];
        this.lastName = arr[1];

    }
}

const p = new Person("c", "yl");
console.log(p.fullName);
p.fullName = "xiao ming"
console.log(p.firstName, p.lastName);

Although this example may not be appropriate, we can recognize the use of get,set accessors. When we use instance. fullName, we actually call the get fullName function, and when we use instance. fullName ='...', we actually call set fullName(...).

Static attributes

In TS, we can declare static attributes or static methods through the static keyword, which are not on the instance object but on the class itself.

class Person {
    firstName: string
    lastName: string

    static Id: number = 666

    constructor(fn: string, ln: string) {
        this.firstName = fn;
        this.lastName = ln;
    }

    static getId () {
        return Person.Id;
    }
}

console.log(Person.getId())

We call the static method on the Person object directly using Person.getId(), and use a static attribute Id in the method.
We successfully printed 666.
Here are two questions for you to think about.

  • Do you think it is feasible to replace Person.Id in getId method with this.Id?
  • If I want to use Person.firstName, do you think that's feasible?
    The first question is actually not difficult, in fact, this is the direction of the problem Person.getId() so call, this is still pointing to the Person object, so there is no problem.
    So think about it for a second.
 class Person {
    firstName: string
    lastName: string

    static Id: number = 666

    constructor(fn: string, ln: string) {
        this.firstName = fn;
        this.lastName = ln;
    }

    static getId () {
        return this.Id;
    }
}
const f = Person.getId;
 console.log(f());

What will be printed by using this in the getId function and calling it as follows? Think about it!

The second problem is that using Person.firstName can cause errors because firstName is the instance part of a class that does not exist until the instance object is generated by the new operator.

abstract class

This should be the last part of this section, but also a very important content.
Abstract keyword (abstract)

abstract class Animal {
    eat () {
        console.log("I can eat it.!")
    }
    abstract bark(): void
}

class Dog extends Animal {
    bark () {
        console.log("Wang Wang Wang");
    }
}

class Cat extends Animal {
    bark () {
        console.log("cat");
    }
}

const d = new Dog();
d.bark();

const c = new Cat();
c.bark();

We define an abstract class Animal, which contains an eat method and an abstract method bark. Note that the bark method only declares that it is not implemented.
Both the Dog and Cat classes inherit from the Animal class. Because of inheritance from abstract classes, we have to rewrite abstract methods that implement the definition of parent classes in subclasses.
It is also worth noting that abstract classes cannot generate instances through new operators.
ok, that's all for class knowledge. In the next section, we'll learn about functions together.

Tags: Attribute Javascript Mobile less

Posted on Tue, 13 Aug 2019 06:41:27 -0700 by overlordofevil