04 ts面向对象, 类, 对象类型补充

目录

类的基本使用

类的继承

类的成员修饰符

类的readonly修饰符

类的get与set访问器

ts中类的参数属性

抽象类与方法abstract

ts检测类型-鸭子类型

ts中类具有的特性

对象类型的属性修饰符

对象类型的索引签名(理解)

接口继承

接口被类实现

严格字面量类型检测

抽象类与接口区别(了解)


类的基本使用

class Person {
  // 在ts中,如果成员有属性,需要在class中声明
  name: string = ''
  age: number = 0

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

const person1 = new Person('zhao', 18)
console.log(person1.name);
console.log(person1.age);



export {}

类的继承

类的继承与js差别不大

class Person {
    // 在ts中,如果成员有属性,需要在class中声明
    name: string = ''
    age: number = 0

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
    eating() {
        console.log('person eating');
    }
}
class Son extends Person {
    height: number = 0
    constructor(name: string,age: number ,height: number) {
        super(name, age)
        this.height = height
    }
    eating() {
        super.eating()           
        console.log('son eating'); 
    }
}
const son = new Son('zhao', 18, 1.88)
son.eating() // person eating,son eating
  
export {}

类的成员修饰符

在ts中,类的属性与方法支持三种修饰符

public: 修饰的是在任何地方可见,共有的属性或方法,不写默认就是public

private: 修饰的是在类本身中可见(实例对象不可访问),私有的属性或方法

protected: 修饰的是仅在类本身级子类中可见,受保护的属性或方法

class Person {
    public name: string = ''
    private age: number = 0
    protected height: number = 0

    constructor(name: string, age: number, height: number) {
        this.name = name
        this.age = age
        this.height = height
    }
    eating() {
        console.log('person eating');
        console.log(this.age, this.height);
    }
}
class Son extends Person {
    constructor(name: string,age: number ,height: number) {
        super(name, age, height)
    }
    run() {
        // console.log(this.age); // 私有,子不能访问
        console.log(this.height); // 保护,子可以访问
    }
}
const person = new Person('qun', 44, 1.77)
console.log(person.name);
// console.log(person.age); // 私有,不能访问
// console.log(person.protected); // 受保护,不能访问


const son = new Son('zhao', 18, 1.88)
// console.log(son.height); // 保护,子类实例对象不能访问

  
export {}

类的readonly修饰符

class Person {
    readonly name: string = ''
    age: number = 0
    height: number = 0

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

}

const person = new Person('qun', 44, 1.77)
console.log(person.name);
// person.name = 'cheng' // 只读,不能修改

  
export {}

类的get与set访问器

class Person {
    // 约定俗成,对于私有属性前加_
    private _name: string = ''
    constructor(name: string) {
        this.name = name
    }
    // set/get 对外开发,主要是可以做一些拦截操作
    set name(newValue) {
        this._name = newValue
    }
    get name() {
        return this._name
    }

}

const person = new Person('qun')
person.name = 'cheng'
console.log(person.name); //cheng

  
export {}

ts中类的参数属性

可以看做是一种语法糖写法

在构造函数参数前添加一个可见性修饰符 public private protected readonly 来创建参数属性,最后这些类属性字段也会得到这些修饰符

class Person {
    // name: string = ''
    // age: number = 0
    // height: number = 0

    // constructor(name: string, age: number, height: number) {
    //     this.name = name
    //     this.age = age
    //     this.height = height
    // }
    // 以下为语法糖
    constructor( public name: string, public age: number, public height: number) {
    }
}

const person = new Person('qun', 44, 1.77)

export {}

抽象类与方法abstract

抽象类不能被实例化

抽象方法存在于抽象类中

抽象类中可以有普通方法(有实现体)

子类必须实现抽象类

// 学过Java的应该对抽象类较为了解,把具体事物的共同特性抽象出来(个人理解)
// 抽象类不能实例化
abstract class Aimal { // 抽象类,所有动物都会吃
    abstract eating() // 抽象方法只能出现在抽象类中,不需要有实现体
}

class Cat extends Aimal {
    // 子类必须实现抽象类的抽象方法
    eating() {
        console.log("猫吃鱼");
    }
}

class Dog extends Aimal {
    eating() {
        console.log("狗吃屎");
    }
}

// 通用方法,这里参数类型是Aimal
function getAimalEat(aimal: Aimal) {
    aimal.eating()
}
// 这里也是多态的体现,继承是多态实现前提,龙生九子各有不同
getAimalEat(new Cat())
getAimalEat(new Dog())

ts检测类型-鸭子类型

// ts类型检测是鸭子类型
// 鸭子类型: 一直鸟 如果它跑起来像鸭子 游起来像鸭子  看着像鸭子 那么它就是鸭子
// 鸭子类型: 只关心属性与行为(方法)不关心是不是对应类型
class Person {
    constructor(public name: string, public age: number) {}
}
class Dog {
    constructor(public name: string, public age: number) {}
}

function getPersonInfo(p: Person) {
    console.log(p.name,p.age);
}

getPersonInfo(new Person('zhao', 18))
getPersonInfo({name: 'yun', age: 12})
getPersonInfo(new Dog('旺财', 3))

export {}

ts中类具有的特性

class Person {}

/**
 * 
 * ts中类具有以下特点
 * 1-可以创建类对应的实例对象
 * 2-类本身可以作为实例的类型
 * 3-类也可以当做有构造签名的函数
 */
const p = new Person()
function needPersonParams(p: Person) {}
function needCP(fn: new ()=>void) {}
needCP(Person)

export {}

对象类型的属性修饰符

type IPerson = {
    // 可选属性
    name?: string,
    // 只读属性
    readonly age: number
}
interface IKun {
    name?: string,
    readonly age: number
}

const p: IPerson = {
    name: 'zhao',
    age: 18
}

export {}

对象类型的索引签名(理解)

// 需求:当我们封装一个函数,参数是一个集合(数组或者元组)能够通过下标索引获取值,有length属性

interface ICollect {
    // index这个字段可以是任意值,不是写死的
    [index: number] : string,
    length: number
}

function needCollect(p: ICollect) {
    console.log(p.length);
    console.log(p[0]);
}

const arr: string[] = ['zhao','li','wang']
const tuple: [string,string] = ['liu', 'hu']

needCollect(arr)
needCollect(tuple)
// needCollect({length: 2})
export {}

接口继承

 减少代码里

对第三库的接口进行再一次封装(当你想获得所有属性时,直接继承过来)

interface IPerson {
    name: string,
    age: number,
    eating: ()=>void
}

interface IKun extends IPerson {
    slogan: string
}
const p: IKun = {
    name: 'zhao',
    age: 18,
    slogan: '你干嘛? 哎呦',
    eating: function() {
    }
}
export{}

接口被类实现

interface IPerson {
    name: string,
    age: number,
    eating: ()=>void
}

interface IKun {
    slogan: string
}
// 接口被类实现,可以继承多个接口
class Student implements IPerson ,IKun {
    // 类必须继承接口的所有属性
    name: string
    age: number
    slogan: string
    
    constructor(name: string, age: number, slogan: string) {
        this.name = name
        this.age = age
        this.slogan = slogan
    }

    eating() {

    }
}
// 以前写法
const temp: IKun = {
    slogan: 'llllllllll'
}
// 类
const p = new Student('zhao',18,'hahaha')
// 可以确认p有接口所有属性
console.log(p.name,p.age,p.slogan);

export{}

严格字面量类型检测

interface Person {
    name: string,
    age: number
}
// height报错
// const p: Person = {
//     name: 'zhao',
//     age: 18,
//     height: 1.88
// }
const obj = {
    name: 'zhao',
    age: 18,
    height: 1.88
}
// 不报错
const p: Person = obj

// 解释
// 第一次创建对象字面量,是fresh(新鲜的)
// 对于新鲜的字面量,会进行严格的类型检测,必须完全满足类型的需求(不能有多余属性)
// 对于不新鲜的,为了方便易用,就没严格检测


export {}

抽象类与接口区别(了解)

 抽象类在很大程度上和接口有点类似: 都可以在其中定义一个方法,让子类或实现类来实现对应方法

1. 抽象类是事物的抽象,抽象类用来捕捉子类的共有特性,接口通常是一些行为的描述

2. 抽象类通常用于一系列关系紧密的类之间,接口只是描述一个类应该具有什么行为

3. 接口可以被多层实现,抽象类只能单一继承

4. 抽象类中可以有实现体,接口中只能有函数声明

抽象类是对事物的抽象,表达is a的关系,猫是动物 (动物可以定义抽象类)

接口是对行为的抽象,表达has a的关系,猫拥有跑,爬树  (跑,爬树可以定义单独接口)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值