目录
类的基本使用
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的关系,猫拥有跑,爬树 (跑,爬树可以定义单独接口)