Typescript 类 (class)

文章介绍了TypeScript中类的基本用法,包括构造器、接口约束、类的继承、类的修饰符(如readonly、private等)、super的使用、静态方法以及get和set方法。还讨论了抽象类的概念及其在派生类中的应用。

基本用法 (通过关键字 class)

// 基本用法
class VueService {
  constructor() {} // 构造器
}

类的约束(通过关键字 implements)

// 接口定义属性类型
interface VueProps {
  name: string
  init: () => void
}

// 约束类
class VueService implements VueProps {
  name: string
  constructor(name: string) {
    this.name = name
  }
  init() {
    console.log(this.name)
  }
}

const service = new VueService('校长')
service.init()

类的继承 (通过关键字 extends)

// 接口定义属性类型  (简单版的虚拟dom)
interface VNode {
  tag: string
  text?: string
  children?: VNode[]
}
interface Dom {
  createElement: (el: string) => HTMLElement
  setText: (el: HTMLElement, text: string) => void
  render: (data: VNode) => HTMLElement
}
class DomService implements Dom {
  constructor() { }
  createElement(el: string) {
    return document.createElement(el)
  }
  setText(el: HTMLElement, text: string) {
    el.textContent = text
  }
  render(data: VNode) {
    const root = this.createElement(data.tag)
    if (data.children && Array.isArray(data.children)) {
      data.children.forEach((item: any) => {
        const child = this.render(item)
        root.appendChild(child)
      })
    }
    if (data.text) {
      this.setText(root, data.text)
    }
    return root
  }
}

interface Options {
  el: HTMLElement | string
}
interface VueProp {
  option: Options
  init: () => void
}
class Vue extends DomService implements VueProp {
  option: Options
  constructor(option: Options) {
    super()
    this.option = option
    this.init()
  }
  init() {
    const data: VNode = {
      tag: 'div',
      children: [
        {
          tag: 'p',
          text: '我是子节点P'
        },
        {
          tag: 'span',
          text: '我是子节点span'
        }
      ]
    }
    const app = document.querySelector(`#${this.option.el}`)
    const child = this.render(data)
    app?.appendChild(child)
  }
}
new Vue({
  el: 'app'
})

类的修饰符 (readonly | private | protected | public)

  • readonly 表示只读, 不能修改 (只能在构建的是否赋值一次)
  • private 添加这个修饰符, 只能在自己内部使用 (自身外部都无法使用) [约束的类型里也不能出现]
  • protected 只能给子类 和 自身内部使用 (外部无法使用)
  • public 默认就是 public (可以给自身, 子类 以及外部使用)

super 原理 (父类的 prototype.constructor.call 指向的是父类的原型)

  • 案例一
class Parent {
  constructor() {}
  render() {
    console.log(11111)
  }
}
class Child extends Parent {
  constructor() {
    super() // 父类的prototype.constructor.call  指向的是父类的原型
    this.render()
  }
}
  • 案例二
class Parent {
  name: string
  constructor(name: string) {
    this.name = name
  }
  render() {
    console.log(11111)
    console.log(this.name)
  }
}
class Child extends Parent {
  constructor(name: string) {
    super(name) // 父类的prototype.constructor.call  指向的是父类的原型
    this.render()
    // super.render()
  }
}
new Child('小可爱')

静态方法 (通过关键字 static)

  • 静态方法中的 this 只能指向静态方法或静态变量
  • 静态方法只能用类的原型调用
class Parent {
  name: string
  static age: number = 1233
  constructor(name: string) {
    this.name = name
  }
  render() {
    console.log(11111)
    console.log(this.name)
  }
  // 静态方法
  static version() {
    console.log('0.0.1')
    console.log(this.age)
  }
  // 静态方法
  static show() {
    this.version()
  }
}
const parents = new Parent('校长')
parents.render()

Parent.show() // 静态方法的调用

get 与 set 方法

  • 这两个方法 与 Object.defineProperty() 方法中的 set 与 get 很像
  • 可以认为是个拦截器
interface Person {
  name: string
  age: number
  [propName: string]: any
}

class Student implements Person {
  name: string
  age: number
  class: string
  constructor(name: string, age: number) {
    this.name = name
    this.age = age
    this.class= '一年级'
  }

  get info() {
    return `${this.name}_${this.age}岁_${this.class}`
  }
  set info(newValue) {
    this.class = newValue
  }
}

const students = new Student('战三', 16)
console.log(students.info)  // 战三_16岁_一年级
students.info = '高三'
console.log(students.info);  // 战三_16岁_高三

抽象类 (通过 abstract 关键字)

  • abstract 所定义的类是抽象类, 不能实例化
  • abstract 所定义的方法, 都只是进行一个描述, 无法进行实现
  • 可以用 派生类 来继承 抽象类
  • 派生类中要实现抽象类中用 abstract 定义的方法
  • 派生类可以被实例化

  1. 抽象类
// 抽象类
abstract class Vue {
  name: unknown
  constructor(name?: string) {
    this.name = name
  }
  showName(): unknown {  // 这里没有用abstract, 可以正常编译
    return this.name
  }
  abstract init(name: string): void  // 这是用到abstract, 他只能进行描述, 无法实现像showName 的代码操作
}

new Vue()  // 这里会报错, 不能实例化abstract定义的抽象类
  1. 派生类
// 抽象类
abstract class Vue {
  name: unknown
  constructor(name?: string) {
    this.name = name
  }
  showName(): unknown {  // 这里没有用abstract, 可以正常编译
    return this.name
  }
  abstract init(name: string): void  // 这是用到abstract, 他只能进行描述, 无法实现像showName 的代码操作
}
// 派生类
class Angular extends Vue {
  constructor() {
    super()
  }
  init(name: string) {  // 在派生类中要实现抽象类中用abstract定义的方法
    this.name = name
  }
}
const angular = new Angular()  // 派生类可以实例化
angular.init('小花')
console.log(angular.showName());  // 小花

<think>好的,我现在需要帮助用户了解如何在TypeScript中定义。首先,我得回忆一下TypeScript的基本语法和特性。根据用户提供的引用内容,特别是引用[3]和引用[4],里面提到了构造函数的定义、继承以及访问修饰符的使用。 首先,TypeScript中使用`class`关键字定义,这一点和ES6的JavaScript似,但TypeScript增加了型注解和访问修饰符。例如,用户提到的`public`、`protected`这些修饰符,用来控制属性和方法的访问权限。比如在引用[3]的代码中,`public alias: string`表示`alias`是一个公有属性,而`protected secretIdentity`则是受保护的,只能在及其子中访问。 接下来是构造函数。TypeScript中的构造函数使用`constructor`方法,参数可以带有型注解。例如,在引用[3]的示例中,构造函数接收四个参数,每个参数都有明确的型声明。需要注意的是,如果子继承父,构造函数中必须调用`super()`来初始化父的属性,如`SuperVillain`中的`super(a, b, c, d)`。 然后,属性声明方面,用户可能在问如何声明的属性。在TypeScript中,的属性可以在构造函数参数中直接声明,如`public health: number`,这同时声明了参数型和的属性。也可以在体中显式声明,如引用[3]中的`flaws = ["hubris", "always explains evil plan"];`,这里虽然没有型注解,但TypeScript会根据赋值推断型为字符串数组。 关于继承,使用`extends`关键字,子可以继承父的属性和方法。在引用[3]的例子中,`SuperVillain`继承自`ComicBookCharacter`,并且在构造函数中需要先调用`super()`才能使用`this`。这里用户提供的代码有一个小错误,`console.log('${this.alias}')`中的字符串应该使用反引号(`)才能进行模板字符串替换,但可能用户只是示例中的笔误。 另外,引用[4]提到了强型属性声明,例如`_name`属性在中显式声明型,这样在实例化时会有型检查。例如`let human = new Human('foo');`,构造函数需要接收一个字符串参数,否则会报错。 用户可能还关心的方法定义。TypeScript中的方法和JavaScript似,但可以添加型注解。例如,定义一个方法时,参数和返回值都可以指定型,如`attack(target: Enemy): void { ... }`。 需要注意的是,用户提供的引用中有关于联合型和交叉型的内容(引用[1]),虽然这些属于TypeScript的高级型,但在定义时可能也会用到,例如属性可以是联合型。不过用户的问题集中在的基础定义,这部分可能暂时不需要深入。 综合这些信息,我应该分步骤解释的定义,包括属性声明、构造函数、访问修饰符、继承和方法定义。同时要指出示例代码中的常见错误,比如`super()`的调用顺序和字符串模板的使用,确保用户能够正确应用这些概念。 最后,生成相关问题时要围绕的其他相关特性,如私有属性、静态成员、抽象等,以及实际应用中的常见问题,帮助用户进一步学习。</think>### TypeScript的定义方法 在TypeScript中,通过`class`关键字定义,支持**访问修饰符**(如`public`/`private`/`protected`)、**型注解**和**继承**等特性。以下是具体步骤和示例: --- #### 1. **基础定义** ```typescript class Animal { // 显式声明属性型 name: string; age: number; // 构造函数参数添加型注解 constructor(name: string, age: number) { this.name = name; this.age = age; } // 方法定义 makeSound(): void { console.log("Animal sound"); } } ``` --- #### 2. **简化属性声明** 通过构造函数参数直接声明属性(需配合访问修饰符): ```typescript class Human { // 在构造函数参数中直接声明属性 constructor( public _name: string, private _age: number ) {} greet(): string { return `Hello, ${this._name}`; } } ``` 此时`_name`和`_age`会自动成为的属性[^4]。 --- #### 3. **继承与`super`调用** 子通过`extends`继承父,需在构造函数中优先调用`super()`: ```typescript class SuperHero extends Human { power: string; constructor(name: string, age: number, power: string) { super(name, age); // 初始化父属性 this.power = power; } usePower(): void { console.log(`Using ${this.power}!`); } } ``` ⚠️ 若父构造函数有参数,子必须传递对应参数给`super()`[^3]。 --- #### 4. **访问修饰符** - `public`: 默认修饰符,允许任意访问 - `private`: 仅内部可访问 - `protected`: 及其子可访问 ```typescript class BankAccount { public readonly id: string; // 只读属性 private _balance: number; // 私有属性 constructor(id: string) { this.id = id; this._balance = 0; } // 通过方法访问私有属性 get balance(): number { return this._balance; } } ``` --- #### 5. **静态成员** 通过`static`关键字定义级别的属性和方法: ```typescript class MathUtils { static PI: number = 3.14159; static calculateCircleArea(radius: number): number { return this.PI * radius ** 2; } } // 调用静态方法 MathUtils.calculateCircleArea(5); ``` --- #### § 1. TypeScript中`private`和`protected`修饰符的具体区别? 2. 如何实现抽象(Abstract Class)? 3. 与接口(Interface)在型约束上的差异? 4. 如何通过装饰器(Decorator)增强功能? 5. 型守卫(Type Guard)在继承中的应用场景? [^1]: 联合型与交叉型的语法特性 [^3]: 继承的构造函数调用示例 [^4]: 属性声明与型注解的实践方法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值