TypeScript 面向对象学习

1. 定义类

类的属性:

  • 实例属性:直接定义的属性,通过对象的实例访问
  • 静态属性(类属性):static开头,无需创建实例,通过去访问
  • 只读属性:readonly开头,无法修改

类的方法:

  • 实例方法:直接定义的方法
  • 类方法:static开头,通过类去访问
class Person {
    
    
    // 直接定义的属性
    age = 18;
    // 静态属性(类属性)
    static gender = 'man';
    // 只读属性
    readonly name = 'Jack';

    // 实例方法
    sayHello() {
    
    
        console.log('Hello!');
    }

    // 类方法
    static sayHi() {
    
    
        console.log('Hi!');
    }
}

const Jack = new Person();

console.log(Jack.name);
console.log(Jack.age);
console.log(Person.gender);

Jack.sayHello();
Person.sayHi();

2. 构造函数

constructor()被称为构造函数,构造函数会在创建实例对象时自动调用。

  • 在实例方法中,this表示当前当前的对象实例

  • 在构造函数中,当前对象就是当前新建的对象

  • 可以通过this向新建的对象中添加属性

class Dog {
    
    
    name: string;
    age: number;

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

    bark() {
    
    
        console.log(this.name);
    }
}

const dog = new Dog('小黑', 2);
const dog2 = new Dog('小白', 3);

dog.bark(); // 小黑
dog2.bark(); // 小白

3. 继承

  • 使用关键字extends实现继承
  • 子类将会拥有父类所有的方法和属性
  • 可以在子类中添加父类没有的属性和方法
  • 重写:子类中添加了和父类相同的方法,则子类方法会覆盖掉父类的方法
  • 在类的方法中,super表示当前类的父类
  • 子类中写了构造函数,必须在子类构造函数中手动父类的构造函数进行调用(super表示父类)
// 父类
class Animal {
    
    
    name: string;
    age: number;

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

    sayHello() {
    
    
        console.log('动物叫~');
    }
}

// 子类:狗
class Dog extends Animal {
    
    
    sayHello() {
    
    
        console.log('wang wang~');
        // super就表示当前类的父类
        super.sayHello();
    }
}

// 子类:猫
class Cat extends Animal {
    
    
    gender: string;

    constructor(name: string, age: number, gender: string) {
    
    
        // 手动调用父类的构造函数,参数为name, age
        super(name, age);
        this.gender = gender;
    }

    run() {
    
    
        console.log(`${
      
      this.name}在跑!`);
    }
    sayHello() {
    
    
        console.log('miao miao~');
    }
}

const dog = new Dog('柯基', 2);
const cat = new Cat('布偶', 4, '雌');

dog.sayHello();
// wang wang~
// 动物叫~

console.log(cat); // Cat { name: '布偶', age: 4, gender: '雌' }
cat.run(); // 布偶在跑!

4. 抽象类、抽象方法

  • abstract开头的类是抽象类
  • 抽象类不能用来创建对象,是专门用来被继承的类
  • 抽象类中可以添加抽象方法,以abstract开头,没有方法体
  • 抽象方法只能定义在抽象类接口中,子类必须对抽象方法进行重写
abstract class Animal {
    
    
    name: string;

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

class Dog extends Animal {
    
    
    age: number;

    constructor(name: string, age: number) {
    
    
        super(name);
        this.age = age;
    }
    sayHello() {
    
    
        console.log(`我是${
      
      this.name}`);
    }
}


const dog = new Dog('旺财', 2);
dog.sayHello(); // 我是旺财

5. 接口

  • 接口interface用来定义一个类结构,规定应该包含的属性和方法

  • 也可以当成类型声明去使用

  • 接口中的所有的属性都不能有实际的值,只定义对象的结构

  • 接口中所有的方法都是抽象方法

  • 定义类时,可以使类去实现一个接口

    class 类名 implements 接口名{}

// 定义接口
interface myInterface {
    
    
    name: string;
}

// 补充这个接口
interface myInterface {
    
    
    age: number;
    sayHello(): void;
}

class Person implements myInterface {
    
    
    name: string;
    age: number;
    constructor(name: string, age: number) {
    
    
        this.name = name;
        this.age = age;
    }
    sayHello() {
    
    
        console.log('Hello~');
    }
}

6. 属性封装

属性修饰符

对象实质上就是属性和方法的容器,它的主要作用就是存储属性和方法,这就是所谓的封装。定义类时,可以在属性前添加属性的修饰符

  • public:公有属性,可以在任意位置访问(修改),默认值
  • private:私有属性,只能在类内部进行访问(修改),但外部可以利用类的方法访问私有属性
  • protected:受保护的属性,只能在当前类当前类的子类中访问(修改)

可以直接将属性定义在构造函数中,以下两端代码等价

class Person {
    
    
    name: string;
    age: number;
    constructor(name: string, age: number) {
    
    
        this.name = name;
        this.age = age;
    }
}
class Person {
    
    
    constructor(public name: string, public age: number) {
    
     }
}
// public不能忘记

属性存取器

  • 对于一些不希望被任意修改的属性,可以将其设置为private
  • 直接将其设置为private将导致无法再通过对象修改其中的属性
  • 我们可以在类中定义一组读取、设置属性的方法,这种对属性读取或设置的属性被称为属性的存取器
  • 读取属性的方法叫做setter方法,设置属性的方法叫做getter方法
class Person {
    
    
    private age: number;
    constructor(_age: number) {
    
    
        this.age = _age;
    }
    get _age() {
    
    
        return this.age;
    }
    set _age(value) {
    
    
        if (value > 0) {
    
    
            this.age = value;
        }
    }
}

const Tom = new Person(12);
// “age”为私有属性,只能在类“Person”中访问
// 所以访问的是 _age
Tom._age = 18; // 可以更改
console.log(Tom._age); // 18
Tom._age = -18; // 不满足条件,无法更改
console.log(Tom._age); //  18

7. 泛型

在定义函数时,如果遇到类型不明确就可以使用泛型

function fn<T>(a: T): T {
    
    
    return a;
}

// 可以直接调用具有泛型的函数
let result = fn(10); // 不指定泛型,TS可以自动对类型进行推断
let result2 = fn<string>('hello'); // 指定泛型
// 泛型可以同时指定多个
function fn<T, K>(a: T, b: K): T {
    
    
    console.log(b);
    return a;
}
fn<number, string>(123, 'hello');
// 定义类时可以使用泛型
class MyClass<T>{
    
    
    name: T;
    constructor(name: T) {
    
    
        this.name = name;
    }
}
const Person = new MyClass<string>('Jack');
interface Inter {
    
    
    length: number;
}

// T extends Inter 表示泛型T必须是Inter实现类(子类)
function fn<T extends Inter>(a: T): number {
    
    
    return a.length;
}

猜你喜欢

转载自blog.csdn.net/Jack_lzx/article/details/115033645