首页 Order Typescript 正文

Typescript 类相关

金鹏头像 金鹏 Typescript 2024-10-07 11:10:46 0 199
导读:classPerson{ //属性声明 name:string age:number //构造器 const...

class Person {


  // 属性声明

  name: string


  age: number


  // 构造器

  constructor(name: string, age: number) {


    this.name = name


    this.age = age


  }


  // 方法

  speak() {


    console.log(`我叫:${this.name},今年${this.age}岁`)


  }


}



// Person实例

const p1 = new Person('周杰伦', 38)


class Student extends Person {


  grade: string


  // 构造器

  constructor(name: string, age: number, grade: string) {


    super(name, age)


    this.grade = grade


  }


  // 备注本例中若Student类不需要额外的属性,Student的构造器可以省略



  // 重写从父类继承的方法

  override speak() {


    console.log(`我是学生,我叫:${this.name},今年${this.age}岁,在读${this.grade}年级`,)


  }


  // 子类自己的方法

  study() {


    console.log(`${this.name}正在努力学习中......`)


  }


}


属性修饰符 

image.png



public 修饰符   


class Person {


  // name写了public修饰符,age没写修饰符,最终都是public修饰符

  public name: string


  age: number


  constructor(name: string, age: number) {


    this.name = name


    this.age = age


  }


  speak() {


    // 类的【内部】可以访问public修饰的name和age

    console.log(`我叫:${this.name},今年${this.age}岁`)


  }


}



const p1 = new Person('张三', 18)


// 类的【外部】可以访问public修饰的属性

console.log(p1.name)


class Student extends Person {


  constructor(name: string, age: number) {


    super(name, age)


  }


  study() {


    // 【子类中】可以访问父类中public修饰的:name属性、age属性

    console.log(`${this.age}岁的${this.name}正在努力学习`)


  }


}


属性的简写形式   


class Person {


  public name: string;


  public age: number;



  constructor(name: string, age: number) {


      this.name = name;


      this.age = age;


  }


}


class Person {


  constructor(


    public name: string,


    public age: number


  ) { }


}


protected 修饰符   


class Person {


  // name和age是受保护属性,不能在类外部访问,但可以在【类】与【子类】中访问

  constructor(


    protected name: string,


    protected age: number


  ) {}


  // getDetails是受保护方法,不能在类外部访问,但可以在【类】与【子类】中访问

  protected getDetails(): string {


    // 类中能访问受保护的name和age属性


    return `我叫:${this.name},年龄是:${this.age}`


  }


  // introduce是公开方法,类、子类、类外部都能使用

  introduce() {


    // 类中能访问受保护的getDetails方法


    console.log(this.getDetails());


  }


}



const p1 = new Person('杨超越',18)


// 可以在类外部访问introduce

p1.introduce()



// 以下代码均报错

// p1.getDetails()

// p1.name

// p1.age


class Student extends Person {


  constructor(name:string,age:number){


    super(name,age)


  }


  study(){


    // 子类中可以访问introduce

    this.introduce()


    // 子类中可以访问name

    console.log(`${this.name}正在努力学习`)


  }


}



const s1 = new Student('tom',17)


s1.introduce()



private 修饰符   


class Person {


  constructor(


    public name: string,


    public age: number,


    // IDCard属性为私有的(private)属性,只能在【类内部】使用

    private IDCard: string


  ) { }


  private getPrivateInfo(){


    // 类内部可以访问私有的(private)属性 —— IDCard

    return `身份证号码为:${this.IDCard}`


  }


  getInfo() {


    // 类内部可以访问受保护的(protected)属性 —— name和age

    return `我叫: ${this.name}, 今年刚满${this.age}岁`;


  }


  getFullInfo(){


    // 类内部可以访问公开的getInfo方法,也可以访问私有的getPrivateInfo方法

    return this.getInfo() + ',' + this.getPrivateInfo()


  }


}



const p1 = new Person('张三',18,'110114198702034432')

console.log(p1.getFullInfo())

console.log(p1.getInfo())



// 以下代码均报错

// p1.name

// p1.age

// p1.IDCard

// p1.getPrivateInfo()


readonly 修饰符   


class Car {


  constructor(


    public readonly vin: string, //车辆识别码,为只读属性


    public readonly year: number,//出厂年份,为只读属性


    public color: string,


    public sound: string


  ) { }



  // 打印车辆信息


  displayInfo() {


    console.log(`


      识别码:${this.vin},


      出厂年份:${this.year},


      颜色:${this.color},


      音响:${this.sound}


    `);


  }


}



const car = new Car('1HGCM82633A123456', 2018, '黑色', 'Bose音响');


car.displayInfo()



// 以下代码均错误:不能修改 readonly 属性


// car.vin = '897WYE87HA8SGDD8SDGHF'; 


// car.year = 2020; 



抽象类


· 概述:抽象类是一种无法被实例化的类,专门用来定义类的结构和行为,类中可以写抽象方法,也可以写具体实现。抽象类主要用来为其派生类提供一个基础结构,要求其派生类必须实现其中的抽象方法。 

· 简记:抽象类不能实例化,其意义是可以被继承,抽象类里可以有普通方法、也可以有抽象方法。


通过以下场景,理解抽象类:


我们定义一个抽象类Package,表示所有包裹的基本结构,任何包裹都有重量属性weight,包裹都需要计算运费。但不同类型的包裹(如:标准速度、特快专递)都有不同的运费计算方式,因此用于计算运费的calculate方法是一个抽象方法,必须由具体的子类来实现。 


abstract class Package {


  constructor(public weight: number) { }


  // 抽象方法:用来计算运费,不同类型包裹有不同的计算方式

  abstract calculate(): number


  // 通用方法:打印包裹详情

  printPackage() {


    console.log(`包裹重量为: ${this.weight}kg,运费为: ${this.calculate()}元`);


  }


}


StandardPackage类继承了Package,实现了calculate方法:


// 标准包裹

class StandardPackage extends Package {


  constructor(


    weight: number,


    public unitPrice: number // 每公斤的固定费率


  ) { super(weight) }



  // 实现抽象方法:计算运费

  calculate(): number {


    return this.weight * this.unitPrice;


  }


}



// 创建标准包裹实例

const s1 = new StandardPackage(10,5)


s1.printPackage()


ExpressPackage类继承了Package,实现了calculate方法:


class ExpressPackage extends Package {


  constructor(


    weight: number,


    private unitPrice: number, // 每公斤的固定费率(快速包裹更高)


    private additional: number // 超出10kg以后的附加费


  ) { super(weight) }



  // 实现抽象方法:计算运费

  calculate(): number {


    if(this.weight > 10){


      // 超出10kg的部分,每公斤多收additional对应的价格


      return 10 * this.unitPrice + (this.weight - 10) * this.additional


    }else {


      return this.weight * this.unitPrice;


    }


  }


}



// 创建特快包裹实例

const e1 = new ExpressPackage(13,8,2)


e1.printPackage()


总结:何时使用抽象类?

1. 定义通用接口:为一组相关的类定义通用的行为(方法或属性)时。 

2. 提供基础实现:在抽象类中提供某些方法或为其提供基础实现,这样派生类就可以继承这些实现。

3. 确保关键实现 :强制派生类实现一些关键行为。

4. 共享代码和逻辑:当多个类需要共享部分代码时,抽象类可以避免代码重复。 



interface(接口)

interface是一种定义结构的方式,主要作用是为:类、对象、函数等规定一种契约,这样可以确保代码的一致性和类型安全,但要注意interface只能定义格式,不能包含任何实现 !


定义类结构   


// PersonInterface接口,用与限制Person类的格式

interface PersonInterface {


  name: string


  age: number


  speak(n: number): void


}



// 定义一个类 Person,实现 PersonInterface 接口

class Person implements PersonInterface {


  constructor(


    public name: string,


    public age: number


  ) { }


  // 实现接口中的 speak 方法

  speak(n: number): void {


    for (let i = 0; i < n; i++) {


      // 打印出包含名字和年龄的问候语句


      console.log(`你好,我叫${this.name},我的年龄是${this.age}`);


    }


  }


}



// 创建一个 Person 类的实例 p1,传入名字 'tom' 和年龄 18

const p1 = new Person('tom', 18);


p1.speak(3)


定义对象结构   


interface UserInterface {


  name: string


  readonly gender: string // 只读属性


  age?: number // 可选属性


  run: (n: number) => void


}



const user: UserInterface = {


  name: "张三",


  gender: '男',


  age: 18,


  run(n) {


    console.log(`奔跑了${n}米`)


  }


};



定义函数结构   

interface CountInterface {


  (a: number, b: number): number;


}



const count: CountInterface = (x, y) => {


  return x + y


}


接口之间的继承   


 一个interface继承另一个interface,从而实现代码的复用


interface PersonInterface {


  name: string // 姓名


  age: number // 年龄


}



interface StudentInterface extends PersonInterface {


  grade: string // 年级


}



const stu: StudentInterface = {


  name: "张三",


  age: 25,


  grade: '高三',


}


接口自动合并(可重复定义)   


// PersonInterface接口

interface PersonInterface {


  // 属性声明

  name: string


  age: number


}



// 给PersonInterface接口添加新属性

interface PersonInterface {


  // 方法声明


  speak(): void


}



// Person类实现PersonInterface

class Person implements PersonInterface {


  name: string


  age: number


  // 构造器

  constructor(name: string, age: number) {


    this.name = name


    this.age = age


  }


  // 方法

  speak() {


    console.log('你好!我是老师:', this.name)


  }


}


总结:何时使用接口?

1. 定义对象的格式: 描述数据模型、API 响应格式、配置对象........等等,是开发中用的最多的场景。

2. 类的契约:规定一个类需要实现哪些属性和方法。

3. 扩展已有接口:一般用于扩展第三方库的类型, 这种特性在大型项目中可能会用到。


一些相似概念的区别


1. interface 与 type 的区别

· 相同点:interface和type 都可以用于定义对象结构,在定义对象结构时两者可以互换。

· 不同点:

1️⃣interface:更专注于定义对象和类的结构,支持继承、合并。

2️⃣type:可以定义类型别名、联合类型、交叉类型,但不支持继承和自动合并。


// 使用 interface 定义 Person 对象

interface PersonInterface {


  name: string;


  age: number;


  speak(): void;


}



// 使用 type 定义 Person 对象

type PersonType = {


  name: string;


  age: number;


  speak(): void;


};



// 使用PersonInterface

/* let person: PersonInterface = {


  name:'张三',


  age:18,


  speak(){


    console.log(`我叫:${this.name},年龄:${this.age}`)


  }


} */



// 使用PersonType

let person: PersonType = {


  name:'张三',


  age:18,


  speak(){


    console.log(`我叫:${this.name},年龄:${this.age}`)


  }


}


interface PersonInterface {


  name: string // 姓名


  age: number // 年龄


}



interface PersonInterface {


  speak: () => void


}



interface StudentInterface extends PersonInterface {


  grade: string // 年级


}



const student: StudentInterface = {


  name: '李四',


  age: 18,


  grade: '高二',


  speak() {


    console.log(this.name,this.age,this.grade)


  }


}


// 使用 type 定义 Person 类型,并通过交叉类型实现属性的合并

type PersonType = {


  name: string; // 姓名


  age: number; // 年龄


} & {


  speak: () => void;


};



// 使用 type 定义 Student 类型,并通过交叉类型继承 PersonType

type StudentType = PersonType & {


  grade: string; // 年级


};



const student: StudentType = {


  name: '李四',


  age: 18,


  grade: '高二',


  speak() {


    console.log(this.name, this.age, this.grade);


  }


};


14.2. interface 与 抽象类的区别

· 相同点:都能定义一个类的格式(定义类应遵循的契约) 

· 不相同:

1️⃣接口:只能描述结构,不能有任何实现代码,一个类可以实现多个接口。

2️⃣抽象类:既可以包含抽象方法,也可以包含具体方法, 一个类只能继承一个抽象类。


// FlyInterface 接口

interface FlyInterface {


  fly(): void;


}



// 定义 SwimInterface 接口

interface SwimInterface {


  swim(): void;


}



// Duck 类实现了 FlyInterface 和 SwimInterface 两个接口

class Duck implements FlyInterface, SwimInterface {


  fly(): void {


    console.log('鸭子可以飞');


  }



  swim(): void {


    console.log('鸭子可以游泳');


  }


}



// 创建一个 Duck 实例

const duck = new Duck();


duck.fly(); // 输出: 鸭子可以飞


duck.swim(); // 输出: 鸭子可以游泳 







本文地址:https://www.jinpeng.work/?id=225
若非特殊说明,文章均属本站原创,转载请注明原链接。
广告3

欢迎 发表评论:

  • 请填写验证码

日历

«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930

控制面板

您好,欢迎到访网站!
  查看权限
广告2

退出请按Esc键