149 阅读4分钟

类的基本实现

  • 先看一个类
    class Dog {
        constructor(name:string){
            this.name = name;
        }
        name:string
        run(){}
    }
  • 类的属性是原型属性,不是实例属性
    //打印类的实例,可以看出类的属性在实例上,不是在原型上
    let dog = Dog('aa')
    console.log(dog)

  • 类成员的方法是实例方法,不是原型方法
    //打印Dog类的原型,可以看出只有run方法,没有name属性
    console.log(Dog.prototype)

  • 实例的属性必须具有初始值,或者在构造函数中被初始化
    class Dog {
        constructor(name:string){
            //把在构造函数中初始化的去掉,ts就会报错,需要有初始值
            //this.name = name; 
        }
        name:string = 'aa' //此时必须在这里赋值
        run(){}
    }

类的继承

  • 使用extends关键字实现继承
    //父类
    class Dog {
        constructor(name:string){
            this.name = name;
        }
        name:string
        run(){}
    }
    //子类
    class Husky extends Dog {
        constructor(name:string,color:string){
            super(name) //必须有,父类的实例
            this.color = color //一定在super之后调用
        }
        //自己的属性,也需要在构造函数中初始化
        color:string;
    }

类的成员修饰符

  • public :公共成员,默认
  • private:私有成员
    • 只能被类的本身调用,不能被子类和类的实例调用
    //父类
    class Dog2 {
        constructor(name:string){
            this.name = name;
        }
        name:string
        run(){}
        private pro(){} //私有成员
    }
    let dog2 = new Dog2('aa')
    dog2.pro() //会报错,不能被类的实例调用
    
    //子类
    class Husky2 extends Dog2 {
        constructor(name:string,color:string){
            super(name) //必须有,父类的实例
            this.color = color //一定在super之后调用
            // this.pro()  私有成员也不能在子类中调用
        }
        //自己的属性
        color:string;
    }
  • 给构造函数加上私有成员属性
    • 作用:这个类既不能被实例话,也不能被继承
    class Dog3 {
        private constructor(name:string){
            this.name = name;
        }
        name:string
        run(){}
        private pro(){} //私有成员
    }
  • protected:受保护成员
    • 只能在类和子类中访问,不能在类的实例中访问
    • 在构造函数上加上protected,只能被实例化,不能被继承
    class Dog3 {
        protected constructor(name:string){
            this.name = name;
        }
        name:string
        run(){}
        protected pri(){} //受保护成员
    }
  • static:静态成员属性
    • 只能通过类名调用
  • 只读属性:readonly,必须初始化
  • 构造函数的参数也可以加成员修饰符
    • 作用:将参数自动变成实例的属性,在类中省略定义
    class Dog4 {
        //name加上了成员修饰符,表示是实例的属性
        constructor(public name:string){
            this.name = name;
        }
        //name:string 这里就可以去掉了
    }

抽象类

  • 用abstract关键字定义
  • 只能被继承,不能被实例化
    //抽象类
    abstract class Animal {

    }
    //会报错,抽象类不能被实例化,只能被继承
    // let animal = new Animal() 
    
    class Cat extends Animal{
        constructor(name:string){
            super()
            this.name = name;
        }
        name:string
        run(){}
    }
    console.log(Cat.prototype)
    let cat = new Cat('aa')
    console.log(cat)
  • 在抽象类中定义方法,在子类中可以直接调用,实现方法复用
    abstract class Animal {
        eat(){
            console.log('eat')
        }
    }
    // let animal = new Animal() 会报错,抽象类不能被实例化,只能被继承
    
    class Cat extends Animal {
        constructor(name:string){
            super()
            this.name = name;
        }
        name:string
        run(){}
    }
    let cat = new Cat('aa')
    //调用父类的eat方法
    cat.eat()
    console.log(cat)
  • 抽象方法:在抽象类中,不具体实现方法,在子类中具体实现
    abstract class Animal {
        eat(){
            console.log('eat')
        }
        //抽象方法,不具体实现
        abstract sleep () : void
    }
    // let animal = new Animal() 会报错,抽象类不能被实例化,只能被继承
    
    class Cat extends Animal {
        constructor(name:string){
            super()
            this.name = name;
        }
        name:string
        run(){}
        //抽象方法在子类中具体实现
        sleep(){
            console.log('sleep')
        }
    }
    let cat = new Cat('aa')
    //调用父类的eat方法
    cat.eat()
    console.log(cat)

多态

  • 在抽象类中定义一个抽象方法,在不同子类中实现不同的这个抽象方法,在运行的时候运行不同的方法
    abstract class Animal {
        abstract sleep ():void //抽象方法
    }
    //Cat类
    class Cat extends Animal {
        constructor:string){
            super()
        }
        sleep(){
            console.log('sleep')
        }
    }
    let cat = new Cat()
    //APP类
    class App extends Animal {
        sleep(){
            console.log('app')
        }
    }
    let app = new App()
    
    //多态
    let animals:Animal[] = [cat,app]
    animals.forEach(item => {
        item.sleep()
    })
  • 类的链式调用
    • 返回this
    class Work {
        step1(){
            return this
        }
        step2(){
            return this
        }
    }
    new Work().step1().step2()
    
    class MyWork extends Work {
        next(){
            return this;
        }
    }
    new MyWork().next().step1().step2()

类和接口的关系

  • 使用关键字implements
  • 类实现接口时,必须声明接口中所有声明
    interface Human {
        name:string;
        eat():void;
    }
    class Asian implements Human {
        constructor(name:string){
            this.name = name
        }
        name:string
        eat(){}
    }
  • 接口只能约束类的公有成员,不能约束类的构造函数
    interface Human {
        name:string;
        eat():void;
    }
    class Asian implements Human {
        constructor(name:string){
            this.name = name
        }
        //私有成员会报错
        private name:string
        eat(){}
    }
  • 接口继承
    interface Human {
        name:string;
        eat():void;
        sleep():void;
    }
    class Asian implements Human {
        constructor(name:string){
            this.name = name
        }
        name:string
        eat(){}
        sleep(){}
    }
    interface Man extends Human {
        cry():void
    }
    
    interface Child {
        run():void
    }
    
    interface Boy extends Child,Man {
        
    }
    
    let boy:Boy = {
        name:'',
        eat(){},
        sleep(){},
        cry(){},
        run(){},
    }
  • 接口继承类
    //接口继承类
    class Auto {
        state = 1
    }
    interface AutoInterface extends Auto {
    
    }
    class C implements AutoInterface {
        state = 1
    }
    //接口继承子类
    class Bus extends Auto implements AutoInterface {
    
    }