TypeScript の 类 接口

创建一个对象

class Person{
    public name:string;
    public age:number;
    constructor(name:string, age:number){
        this.name = name;
        this.age = age;
    }
}
let a = new Person("测试", 15);
console.log(a.name  + " --- " + a.age)

继承

class NewPerson extends Person{
    public sex: number;
    constructor(sex: number){
        this.sex = sex;
    }
}

由图可见,上面的继承是不正常的,所以这里需要调用其super方法

class NewPerson extends Person{
    public sex: number;
    constructor(name:string,age:number,sex: number){
        super(name,age);
        this.sex = sex;
    }
}

私有属性

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

let c = new PrivatePerson("wz");
console.log(c.name) // 提示报错
这个就是私有属性,那么我们该怎么访问这个私有属性呢?
class PrivatePerson{
    private name:string;
    constructor(name:string){
        this.name = name;
    }
    get getName(){
        return this.name;
    }
}

let c = new PrivatePerson("wz");
console.log(c.getName)

通过上述的get修饰的属性(看起来更像一个方法),便可以获取到私有属性,最后可以通过c.getName获取到

get获取属性,那么是否有set设置属性呢???
class PrivatePerson{
    private name:string;
    constructor(name:string){
        this.name = name;
    }
    get getName(){
        return this.name;
    }
    set setName(name: string){
        this.name = name
    }
}

let c = new PrivatePerson("wz");
console.log(c.getName)
c.setName = "哈哈";
console.log(c.getName)

通过上面set的案例,我们应该清楚的看到,其实getset修饰的都不是方法,而是属性,因为方法的调用fn(),而这个看起来更像是属性的写法,所以这里注意c.setName = "哈哈",既然这样,为了美观,我们将上面的进行一个修改

class PrivatePerson{
    private _name:string;
    constructor(name:string){
        this._name = name;
    }
    get name(){
        return this._name;
    }
    set name(name: string){
        this._name = name
    }
}

let c = new PrivatePerson("wz");
console.log(c.name)
c.name = "哈哈";
console.log(c.name)

这样看起来就完全一样了

私有属性作用是什么呢?
实现单例模式
class SimpleObject {
    //静态方法中只能调用静态变量
    private static simpleInfo: SimpleObject;

    //私有化构造函数,让其无法被外界`new`出来
    private constructor(){}

    //提供公共的静态的获取实例方法
    public static getInstance(){
        //判断实例是否存在
        if(!this.simpleInfo){
            //不存在就实例化一个
            this.simpleInfo = new SimpleObject();
        }
        //返回实例
        return this.simpleInfo;
    }
}

以上的单例模式很简单,但是也需要注意几个小点

  • 因为我们需要实现"单例模式",所以必须要限制实例化的方式,只能由我们内部提供,所以将构造函数私有化,在前面加上private
  • 获取实例方法: 因为我们把构造函数constructor私有化了,所以外部无法使用new关键字实例化对象,我们必须要提供的获取实例方法getInstance必须可以在不实例化的情况下调用,所以这个方法必须使用static修饰
  • 静态方法只能访问静态的数据,所以这里的实例simpleInfo也是静态的,并且为了不让其被外部直接调用,所以加上private
实现部分属性只能获取,而无法修改
  • 私有属性实现
class PriPerson{
    private _name:string;
    constructor(name :string){
        this._name = name;
    }
    get name(){
        return this._name
    }
}
let e = new PriPerson("一个人");
console.log(e.name)
e.name = "不可修改" //报错
  • readonly实现
class PriPerson{
    public readonly name:string;

    constructor(name :string){
        this.name = name;
    }
}
let e = new PriPerson("一个人");
console.log(e.name)
e.name = "不可修改" //报错

抽象类

有时候需要分类,同一类事物有着公共的特性,公共的方法(但是每个之间实现不同),这个时候我们就可以定义个抽象类,抽出相同的,相同的方法

abstract class Animal{
    getEatOrgan(){
        return "嘴";
    }

    abstract eat():string;
}
class People extends Animal{
    eat(){
        return "使用手抓吃饭";
    }
}
class Pig extends Animal{
    eat(){
        return "使用嘴拱着吃";
    }
}
let animals : [string, string] = ["man", "pig"];
animals.forEach((animal) => {
    let unknownAnimal:Animal;
    unknownAnimal = animal === "man" ? new People() : new Pig();
    console.log("吃饭通用器官:" + unknownAnimal.getEatOrgan(),
    "各自吃饭方式: " + unknownAnimal.eat());
})

结果

接口的继承

我们常常会定义一些接口,用于类型定义及检测,像下面一样

interface Student{
    name:string,
    age:number
}

interface Teacher{
    name:string,
    sex:string
}

const sayHello = (user) => {
    console.log(user.name)
}
let st: Student ={
    name: '张珊',
    age:18
}
let te :Teacher = {
    name:"历史",
    sex:"男"
}
sayHello(st);
sayHello(te);

但是我们发现,sayHello中参数user的推断类型是

这个不是我们想要的,所以我们去定义这个user的类型,用什么呢?是Student还是Teacher,当然是我全都要了

 const sayHello = (user: Student | Teacher) => {
    console.log(user.name)
}
思考,当我们新建对象的时候,这个参数类型是不是一直在添加呢?

这个时候就需要使用我们的接口继承(提取出相同的属性,方法,然后其他子类继承该接口)

interface Person{
    name:string
}

interface Student extends Person{
    age:number
}

interface Teacher  extends Person{
    sex:string
}

const sayHello = (user:Person) => {
    console.log(user.name)
}
let st: Student ={
    name: '张珊',
    age:18
}
let te :Teacher = {
    name:"历史",
    sex:"男"
}
sayHello(st);
sayHello(te);
(0)

相关推荐