类的定义
下面是使用 TS 约束属性并实例化对象
class User {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
getInfo = (): string => {
return `${
this.name}的年龄是${
this.age}`
}
}
const hj = new User('hj', 19)
const hk = new User('hk', 20)
console.log(hj.getInfo()); // hj的年龄是19
console.log(hk.getInfo()); // hk的年龄是20
const users: User[] = [hj, hk]
console.log(users);
// [
// User { getInfo: [Function (anonymous)], name: '张三', age: 19 },
// User { getInfo: [Function (anonymous)], name: 'hk', age: 20 }
// ]
通过约束数组的类型为User
,使其成员只能是 User 类型对象
...
const users: User[] = [hj, hk]
console.log(users);
...
修饰符
public
class User {
public name: string
public age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
public getInfo = (): string => {
return `${
this.name}的年龄是${
this.age}`
}
}
const hj = new User('hj', 19)
const hk = new User('hk', 20)
hj.name = '张三'
protected
protected 修饰符指受保护的,只允许在父类与子类使用,不允许在类的外部使用
class User {
protected name: string
public age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
public getInfo = (): string => {
return `${
this.name}的年龄是${
this.age}` // 内部是可以访问 protected 的
}
}
const hj = new User('hj', 19)
hj.name = '张三' // 属性“name”受保护,只能在类“User”及其子类中访问
console.log(hj.getInfo()); // 张三的年龄是19
private
private 修饰符指私有的,不允许在子类与类的外部使用
- 子类不能访问父类的 private 属性或方法
class Person {
protected name: string
private age: number
protected info = (): string => {
return `${
this.name}的年龄是${
this.age}`
}
}
class User extends Person {
constructor(name: string, age: number) {
super()
this.name = name
this.age = age // 子类不能访问父类的 private 属性或方法
}
public getInfo = (): string => {
return this.info()
}
}
const hj = new User('hj', 19)
console.log(hj.getInfo()); // hj的年龄是19
- 父类声明 private 属性或方法子类不允许覆盖
class Person {
protected name: string
private age: number
private getInfo = (): string => {
return `${
this.name}的年龄是${
this.age}`
}
}
// 类“User”错误扩展基类“Person”。
// 属性“getInfo”在类型“Person”中是私有属性,但在类型“User”中不是
class User extends Person {
constructor(name: string, age: number) {
super()
this.name = name
}
public getInfo = (): string => {
return `姓名:${
this.name}`
}
}
- 修饰符 子类访问或更改父类属性或方法是有限制的
- 父类的 private 不允许只类修改
- 父类的 protected 子类可以修改为 protected 或 public
- 父类的 public 子类只能设置为 public
class Person {
protected name: string
private age: number
}
// 类“User”错误扩展基类“Person”。
class User extends Person {
private name: string // 属性“name”在类型“User”中是私有属性,但在类型“Person”中不是
constructor(name: string, age: number) {
super()
this.name = name
}
public getInfo = (): string => {
return `姓名:${
this.name}`
}
}
readonly
readonly 将属性定义为只读,不允许在类的内部与外部进行修改
类似于其他语言的 const 关键字
class User {
protected name: string
private age: number
readonly sex: string
constructor(name: string, age: number, sex: string) {
this.name = name
this.sex = sex
}
public getInfo = (): string => {
return `姓名:${
this.name},性别${
this.sex}`
}
}
const hj = new User('hj', 19, '男')
console.log(hj.sex); // 男
hj.sex = '保密' // 无法分配到 "sex" ,因为它是只读属性
constructor
构造函数是初始化实例参数使用的,在 TS 中有些细节与其他程序不同
我们可以在构造函数 constructor 中定义属性,这样就不用在类中声明属性了,可以简化代码量
必须要在属性前加上 public、private、readonly 等修饰符才有效
class User {
constructor(public name: string) {
}
getInfo = () => {
return this.name
}
}
const hj = new User('hj')
console.log(hj.getInfo()); // hj
static
static 用于定义静态属性或方法,属性或方法是属于构造函数的
静态属性是属于构造函数的,不是对象独有的,所以是所有对象都可以共享的
语法介绍
下面是 static 使用的语法
class User {
static sex: string = '保密'
static getUserInfo() {
return '性别是' + User.sex
}
}
const hj = new User()
console.log(hj.getUserInfo()); // jsError 属性“getUserInfo”在类型“User”上不存在
console.log(User.getUserInfo()); // 性别是保密
单例模式
当把 construct 定义为非 public 修饰符后,就不能通过这个类实例化对象了。
class User {
protected constructor() {
}
}
const hj = new User(); // 类“User”的构造函数是受保护的,仅可在类声明中访问
我们可以利用这个特性再结合 static 即可实现单例模式,即只实例化一个对象
class User {
static instance: User | null = null;
protected constructor() {
}
public static make(): User {
if (User.instance == null) User.instance = new User;
return User.instance;
}
}
const hj = User.make();
console.log(hj);
get/set
使用 get 与 set 访问器可以动态设置和获取属性,类似于 vue 或 laravel 中的计算属性
class User {
constructor(public _name: string) {
}
public get name () {
return this._name
}
public set name (value: string) {
this._name = value
}
}
const hj = new User('hj')
console.log(hj.name); // hj
hj.name = 'hk'
console.log(hj.name); // hk
abstract
抽象类定义使用 abstract 关键字,抽象类除了具有普通类的功能外,还可以定义抽象方法
- 抽象类可以不包含抽象方法,但抽象方法必须存在于抽象类中
- 抽象方法是对方法的定义,子类必须实现这个方法
- 抽象类不可以直接使用,只能被继承
- 抽象类类似于类的模板,实现规范的代码定义
下例中的子类都有 move 方法,我们可以在抽象方法中对其进行规范定义
class Animation {
protected getPos() {
return {
x: 100, y: 300 }
}
}
class Tank extends Animation {
public move(): void {
}
}
class Player extends Animation {
public move(): void {
}
}
- 抽象方法只能定义,不能实现,即没有函数体
- 子类必须实现抽象方法
abstract class Animation {
abstract move(): void
protected getPos() {
return {
x: 100, y: 300 }
}
}
// 非抽象类“Tank”不会实现继承自“Animation”类的抽象成员“move”
class Tank extends Animation {
// public move(): void {}
}
class Player extends Animation {
public move(): void {
}
}
const tank = new Tank()
const player = new Player()
- 子类必须实现抽象类定义的抽象属性
abstract class Animation {
abstract move(): void
abstract name: string
protected getPos() {
return {
x: 100, y: 300 }
}
}
// 非抽象类“Tank”不会实现继承自“Animation”类的抽象成员“name”
class Tank extends Animation {
// public name = '敌方'
public move(): void {
}
}
class Player extends Animation {
public name = '玩家'
public move(): void {
}
}
const tank = new Tank()
const player = new Player()
抽象类不能被直接使用,只能被继承
abstract class Animation {
abstract move(): void
abstract name: string
protected getPos() {
return {
x: 100, y: 300 }
}
}
const animation = new Animation() // 无法创建抽象类的实例