Before ES6 in JavaScript, we used functions (constructor functions) and created a custom class based on prototypes, but this approach was always confusing, especially for those who are used to object-oriented programming such as Java and PHP.

Abstract a class

The basic unit of object-oriented programming is objects, but objects are instantiated by classes, so the first step is to know how to declare a class.

Declaration of a class

The declaration of a class uses the class keyword, and the class name is similar to the naming rules of variables and functions. The first letter should be capitalized, and the class name followed by a pair of curly braces can be understood as the body of the class. The body of the class consists of three parts: member attribute, constructor, and member method.

classClass name {member properties: constructor: member methods:}Copy the code

Member attribute

We can also use the keywords private, public, and protected to declare member attributes in a class:

  • Public: The declared property has public permissions and can be accessed outside the class. The keyword public can be left unwritten by default.
  • Private: Declared properties have private permissions and can only be accessed inside the current class.
  • Protected: Declared properties have protected privileges and can be accessed from within a derived class of the class.
class Person {
  age: number; // age is equivalent to public age
  private sex: string;
  protected phone: number;
}
Copy the code

The constructor

Constructors are used for class initialization to declare which fields are mandatory and which are non-mandatory.

The constructor argument public name: string is equivalent to the following:

class Person {
  public name: string
  constructor(public name: string) {
    this.name = name; }}Copy the code

Inside the constructor, you can assign values to previously declared member attributes.

class Person {
  ...
  constructor(public name: string, age: number, sex: string, phone? :number) {
    this.age = age;
    this.sex = sex;
    this.phone = phone; }}Copy the code

Members of the method

Member methods should be associated with the object (for example, eat). Methods can also be declared using public, private, protected, etc.

class Person {
  ...
  public eat() {
    const info = this.info();
    console.log(`${info}eat... `);
  }

  private info() {
    return `${this.name} ${this.age} ${this.sex} ${this.phone}`; }}Copy the code

What is an object? As long as we can describe things with attributes and methods we can declare as a class, and then instantiate the object to use this class.

Class

We abstracted a class Person above, but instead of using the class directly, we instantiated one or more objects through the abstract class for our use.

Instantiating an object uses the new keyword, followed by the class to be instantiated.

const zhangsan = new Person('Joe'.18.'male');
const lisi = new Person('bill'.20.'male'.18800000000);

zhangsan.eat(); // Undefined male eat...
lisi.eat(); // Li Si 20 male 18800000000 eat...
Copy the code

Static Static attributes

Static can be used to identify class member attributes and methods as static.

The static keyword modifiers member attributes and methods that belong to a class, regardless of the class instance object, and are shared among multiple objects.

The following example defines the static property language as Chinese, and finally instantiates two objects where language can be called using the class name and is shared between the two objects.

class Person {
  static language: string = 'chinese';

  constructor(public name: string) {}

  info() {
    console.log(` I call:${this.name}And I say:${Person.language}`); }}const zhangsan = new Person('Joe');
zhangsan.info(); // My name is Zhang SAN, I said: Chinese

const lisi = new Person('bill');
lisi.info(); // My name is Li Si, I say: Chinese
Copy the code

Object-oriented programming – Encapsulation

If the member attributes or methods of an object are not encapsulated, they can be obtained externally by reference after instantiation. Data such as user phone cannot be obtained at will.

Encapsulation as one of the important characteristics of object-oriented programming, it is the class internal member attributes, member methods unified protection, only reserved limited interface and external contact, as far as possible to shield the internal details of the object, prevent external arbitrary modification of internal data, to ensure the security of data.

Private keyword modification

Using private keywords to modify the class member attributes and member methods to achieve the encapsulation of members, encapsulated member objects can only be accessed inside the class.

Now we use the private keyword to wrap some members of the Person class, and only the info method can be accessed externally.

class Person {
  private name: string;
  private phone: string;

  constructor(name: string, phone: string) {
    this.name = name;
    this.phone = phone;
  }

  public info() {
    console.log(I was `${this.name}Mobile phone no.${this.formatPhone()}`)}private formatPhone() {
    return this.phone.replace(/(\d{3})\d{4}(\d{3})/.'$1 $2 * * * *'); }}const zhangsan = new Person('Joe'.'18800000000');
zhangsan.info();
Copy the code

Private member access

Member properties or methods decorated with private will not be accessible externally. If access is required, you can set public methods to return private properties. You can also apply some conditions here.

class Person {
  private name: string;
  private phone: string;

  constructor(name: string, phone: string) {
    this.name = name;
    this.phone = phone;
  }

  public getName() {
    return this.name; }... }const zhangsan = new Person('Joe'.'18800000000');
console.log(zhangsan.getName()); / / zhang SAN
Copy the code

Object-oriented programming – Inheritance

An existing class that is used to derive a new class becomes a base class, also known as a superclass. A newly derived class is called a derived class or subclass.

In C++, a derived class can inherit from multiple base classes, including single inheritance and multiple inheritance. In TypeScript, Java, and PHP, only inheritance from a single base class is available.

The following diagram shows a schematic of the Person base class being inherited:

Subclass inheritance application

Create a base class Person with a member attribute name and a member method eat.

class Person {
  protected name: string;

  constructor(name: string) {
    this.name = name;
  }

  eat() {
    console.log('eat... '); }}Copy the code

Create a derived class Student that extends from the base class Person with the keyword extends and implement a custom study method.

class Student extends Person {
  study() {
    this.eat();
    console.log(`${this.name}Start learning... `); }}Copy the code

Create a derived class Work that extends from the base class Person with the keyword extends to implement a custom Work method.

class Work extends Person {
  work() {
    super.eat();
    console.log(`${this.name}Get to work... `); }}Copy the code

The subclasses Student and Work have their own separate methods: students need to learn and workers need to Work, but they need to eat before they can start.

Let’s test this example.

const s1 = new Student('Joe');
s1.study(); 
// eat... 
// Zhang SAN begins to learn...

const w1 = new Work('bill');
w1.work();
// eat...
// Li Si starts to work...
Copy the code

Subclasses override methods of their parent classes

We cannot define functions with the same name, nor can we define methods with the same name in the same class, but in derived classes we can override methods with the same name in the base class.

class Student extends Person {
  constructor(name: string) { super(name); }

  eat() {
    console.log('A bit too much homework today, one more piece of meat! ');
    super.eat();
  }

  study() {
    this.eat();
    console.log(`${this.name}Start learning... `); }}const s1 = new Student('Joe');
s1.study();

// Today is a bit too much homework, one more piece of meat!
// eat...
// Zhang SAN begins to learn...
Copy the code

Note: If the constructor() method is written in a derived class, the super method must be called before this, which calls the base class’s constructor.

Interface inheritance

Interface multiple inheritance implementation

In TS, only single inheritance can be implemented between classes, but in interfaces, single inheritance and multiple inheritance can be implemented.

interface Person1 {
  nickname: string;
}
interface Person2 {
    age: number;
}
interface Person3 extends Person1, Person2 {
    sex: string;
}

function study(obj: Person3) {
    console.log(obj.nickname, obj.age, obj.sex);
}

study({ nickname: 'may', age: 20, sex: 'man' });
Copy the code

Interface inheritance class

An interface can inherit from a class through the extends keyword, and if a class member contains an implementation, its implementation is not inherited.

class Person1 {
    nickname: string;
    
    test(): string {
        return 'Hello'; }}interface Person2 extends Person1 {
    age: number;
}

class Study implements Person2 {
    nickname: string;
    age: number;
    constructor(nickname: string, age: number) {
        this.nickname = nickname;
        this.age=age;
    }

    test(): string {
        console.log(this.nickname, this.age)
        return 'Hi'; }}const lisi = new Study('bill'.20);
console.log(lisi.test());
Copy the code

Object-oriented programming – polymorphism

Polymorphism is one of the three major characteristics of object-oriented programming, can let have inheritance is not the same object, use the same function name to complete different function, popular speak: a subclass can be modified and rewrite the parent class method of the same name, defined in the parent class can be used to abstract class or interface to define the corresponding specification.

An abstract class

Abstract classes are a special class that is modified with the abstract keyword and is not instantiated directly.

Member properties or methods in an abstract class can contain implementation details if they are not decorated with the abstract keyword. If the abstract keyword modifier is used, it can only be defined, and the implementation must be done in a derived class.

abstract class Person {
  abstract name: string;
  eat(): void {
    console.log('eat... ')}abstract walk(): void;
}

class Student extends Person {
  name: string;
  walk(): void {
    console.log('walk... '); }}const zhangsan = new Student();
zhangsan.eat(); // eat...
zhangsan.walk(); // walk...
Copy the code

interface

Interfaces are a special kind of abstract class. Unlike abstract classes, interfaces have no concrete implementation, only definitions, declared by the interface keyword.

As mentioned in inheritance, only single inheritance is possible in TypeScript, but in interfaces, you can implement multiple interfaces.

classThe name of the classimplements Interface1, Interface2 {
  ...
}
Copy the code

Here is an example interface:

  • Define a Person interface
  • Define a Study interface that holds a diploma method
interface Person {
  name: string; phone? :string;
}
interface Student {
  diploma(): void;
} 

class HighSchool implements Student, Person {
  name: string;

  diploma(): void {
    console.log('High school... '); }}class University implements Student, Person {
  name: string;

  diploma(): void {
    console.log('College students... ')}}Copy the code

Application of polymorphism

A classic example is USB interface of computer. We can plug in mouse, keyboard, USB disk and other devices to expand its different functions. The functions of each device are different, but the specification of USB interface is consistent, which is what we call polymorphism. Subclasses override methods with the same name as their parent class to implement their own functionality.

// Define the USB interface specification
interface USB {
  run(): void;
}

// Implement a USB standard keyboard device
class UKey implements USB {
  run(): void {
    console.log('USB standard keyboard devices'); }}// Implement a USB device
class UDisk implements USB {
  run(): void {
    console.log('USB standard USB device '); }}// Computer class
classComputer { useUSB(usb: USB) { usb.run(); }}const computer = new Computer();
computer.useUSB(new UKey()); // USB standard keyboard device
computer.useUSB(new UDisk()); // USB standard USB device
Copy the code

conclusion

During college, I studied PHP development by myself, and one of the books that impressed me most was “PHP in Detail” by author: “Gao Luofeng” had an internship in Beijing during the summer vacation and met the author, which was very Nice. The section about object orientation in the book was quite impressive and well explained. When learning TypeScript object orientation encapsulation, inheritance and polymorphism, many concepts were similar, which was very helpful for understanding.

Reference

  • More on PHP version 2
  • TypeScript Chinese website