Typescript面向对象编程(类、继承、多态、接口、泛型等)详解及案例

Typescript面向对象编程

文章目录

    • Typescript面向对象编程
      • 1、类
      • 2、构造函数和this
      • 3、继承
      • 4、super
      • 5、抽象类
      • 6、接口
      • 7、属性的封装
      • 8、泛型

1、类

在属性前使用static关键字可以定义类属性(静态属性)

直接定义的属性是实例属性,需要通过per对象的实例去访问

static开头的静态属性,可以直接通过类去访问

//使用class关键字来定义一个类
class Person{
    //定义属性
    name:string = "天海";
    //在属性前使用static关键字可以定义类属性(静态属性)
    static age: number = 18;
}

const per = new Person();
//直接定义的属性是实例属性,需要通过per对象的实例去访问
console.log(per);
console.log(per.name);
per.name = "天海一直在";

//static开头的静态属性,可以直接通过类去访问
console.log(Person.age);

只读属性,不能修改

readonly name:string = "天海";

2、构造函数和this

此例中constructor为构造函数

在构造函数中当前对象就是当前新建的那个对象

案例:

class Hero{
    na : string;
    level : number;
    constructor(na:string,level:number){
        //在实例方法中,this就表示当前的实例,可以通过this向新建的对象中添加属性
        this.na = na;
        this.level = level;
    }
    choose(){
        //在方法中通过this来表示当前调用方法的对象
        console.log("您选择了" + this.na);
    }
}
const kasa = new Hero('卡莎',5);
const mow = new Hero('牛头',5);
kasa.choose()
//输出:您选择了卡莎

3、继承

class 子类 extends 父类{}

使用继承后,子类会拥有父类所有的方法和属性

案例:

(function (){
    //定义一个英雄类
    class Hero{
        name:string;
        level:number;
        constructor(name:string,level:number){
            this.name = name;
            this.level = level;
        }
        levelup(){
            this.level += 1
            console.log("我现在" + this.level + "级" );
        }
    }
    class ADC extends Hero{
        shanxian(){
            console.log(`${this.name}有闪现`);
            
        }
    }
    class Support extends Hero{
    	
    }
    const kasa = new ADC('卡莎',1);
    const niutou = new Support('牛头',2);
    console.log(kasa);
    kasa.levelup();
    kasa.shanxian();
    console.log(niutou);
    niutou.levelup();
})();

注:如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父类方法——方法的重写

运行结果:

在这里插入图片描述

4、super

在类的方法中,super就表示当前类的父类

(function(){
    class Hero{
        name:string;
        constructor(name:string){
            this.name = name;
        }
        shanxian(){
            console.log('我有闪现');
        }
    }
    class ADC extends Hero{
        level:number;
        constructor(name:string,level:number){
            super(name);
            this.level = level
        }
        shanxian() {
            super.shanxian();
            console.log('是否使用闪现'); 
        }
    }
    const kasa = new ADC('卡莎',3);
    kasa.shanxian();
})()

5、抽象类

和其他类区别不大,知识不能用来创建对象。

抽象类就是专门用来被继承的类。

不能使用这个类创建对象

abstract class xxx{}

抽象方法: abstract 方法名():void;

抽象方法只能定义在抽象类中

子类必须对抽象方法进行重写,也就是说被继承后的方法是失效的

6、接口

接口中的所有的属性都不能有实际值,只定义对象的结构,接口内所有方法都是抽象方法。

(function(){
    //描述一个对象的类型
    type heroType = {
        name:string,
        level:number
    };

    /* 接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法
    同时接口也可以当初类型声明去使用
    可以重复声明
    */ 

    interface myInterface{
        name:string;
        age:number;
    }
    const myInterface = {
        name:'kasa',
        level:18
    }

})()

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

使类满足接口的要求

7、属性的封装

下方代码中,设置了英雄的名称为私有方法,不可以修改,而等级是可以被修改的。

(function(){
    class Hero{
        //公用属性:public修饰的属性可以在任意位置访问。
        //私有属性:private智能在类内部进行访问。
        private name:string;
        public level:number;

        constructor(name:string,level:number){
            this.name = name;
            this.level = level;
        }
    }
    const per = new Hero('孙悟空',16);
    //name行报错
    per.name = '贾克斯';
    //level行可以通过编译
    per.level = -5;
    console.log(per);
    
})();

但这就出现了问题,英雄等级为负值了,而且英雄的名称即不能被修改也不能被读取到。

我们不允许这种情况发生,所以可以通过getter和setter方法来获取属性并设置条件。

(function(){
    class Hero{
        //都设为私有属性
        private name:string;
        private level:number;

        constructor(name:string,level:number){
            this.name = name;
            this.level = level;
        }
        //属性的存取器,getter用于读取属性,setter用来设置属性
        getName(){
            return this.name;
        }
        getLevel(){
            return this.level
        }
        setLevel(value:number){
            if(value>=0 && value<=18){
                this.level = value;
            }
        }
    }
    const per = new Hero('孙悟空',15);
    //获取并修改属性
    per.getLevel()
    per.setLevel(12);
    console.log(per);
})();

同样的方法,TS提供了get和set关键字

注:方法名和属性名不能重复,这里用 _name和 _level来写方法。

(function(){
    class Hero{
        private name:string;
        private level:number;
        constructor(name:string,level:number){
            this.name = name;
            this.level = level;
        }
        //Ts中设置getter方法的方式
        get _name(){
            return this.name
        }
        get _level(){
            return this.level
        }
        set _level(value){
            if(value>=0 && value<=18){
                this.level = value;
            }
        }
    }
    const per = new Hero('孙悟空',15);
    per.getLevel()
    per.setLevel(12);
    console.log(per);
    
})();

protected:受包含的属性,只能在当前类和当前类的子类中访问(对继承有效)

   class A {
        protected num:number;
        constructor(num:number){
            this.num=num;
        }
    }
    class B extends A{
        test(){
            console.log(this.num);
            
        }
    }

最后再说明一下定义类的简化写法

 class C{
        constructor(public name:string,public level:number){
        }
    }
    const c = new C('xxx',111)
    console.log(c);

8、泛型

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

function fn<T>(a:T):T{
	return a;
}
//调用具有泛型的函数
不指定泛型,TS自动推断
fn(10)
//指定泛型
fn<string>('hello')

可以同时指定多个

function fn2<T,K>(a:T,b:K):T{
	console.log(b);
	return a;
}
fn2<number,string>(123,'hello');

泛型T作为借口的子类

interface Inter{
	length:number;
}
function fn3<T extends Inter>(a:T):number{
	return a.length
}

你可能感兴趣的:(TypeScript,typescript,javascript,前端)