静态属性与方法

使用 static 关键字定义的成员属于类本身,而不是实例。静态成员通过类名直接访问,不需要创建实例。它们常用于定义工具方法、常量和单例模式。

静态属性

静态属性是类级别的变量,所有实例共享同一个值。

class Configuration {
  static appName: string = "我的应用"
  static version: string = "1.0.0"
  static maxConnections: number = 10
}

console.log(Configuration.appName)
console.log(Configuration.version)
console.log(Configuration.maxConnections)

Configuration.maxConnections = 20
console.log(Configuration.maxConnections)

appNameversionmaxConnections 是静态属性,通过类名直接访问。修改静态属性会影响所有使用该属性的地方。

静态方法

静态方法是类级别的函数,不需要实例就能调用。

class MathUtils {
  static PI: number = 3.14159

  static circleArea(radius: number): number {
    return MathUtils.PI * radius * radius
  }

  static circleCircumference(radius: number): number {
    return 2 * MathUtils.PI * radius
  }

  static max(a: number, b: number): number {
    return a > b ? a : b
  }

  static min(a: number, b: number): number {
    return a < b ? a : b
  }
}

console.log(MathUtils.PI)
console.log(MathUtils.circleArea(5))
console.log(MathUtils.circleCircumference(5))
console.log(MathUtils.max(10, 20))

静态方法通常用于工具函数,不需要访问实例数据。在静态方法内部,通过类名访问其他静态成员。

静态与实例的区别

静态成员属于类,实例成员属于对象。理解这个区别很重要。

class Counter {
  static totalCount: number = 0
  count: number = 0

  constructor() {
    Counter.totalCount++
    this.count++
  }

  increment(): void {
    this.count++
    Counter.totalCount++
  }
}

const c1 = new Counter()
const c2 = new Counter()
const c3 = new Counter()

console.log(c1.count)
console.log(c2.count)
console.log(Counter.totalCount)

c1.increment()
console.log(c1.count)
console.log(Counter.totalCount)

totalCount 是静态属性,记录所有实例的总计数。count 是实例属性,每个实例有自己的计数。创建实例时,两个计数都会增加。

静态块

TypeScript 支持静态初始化块,用于执行复杂的静态初始化逻辑。

class Database {
  static connection: any
  static isConnected: boolean = false

  static {
    console.log("初始化数据库连接...")
    Database.connection = { ready: true }
    Database.isConnected = true
  }

  static query(sql: string): any {
    if (!Database.isConnected) {
      console.log("数据库未连接")
      return null
    }
    console.log(`执行查询: ${sql}`)
    return []
  }
}

console.log(Database.isConnected)
Database.query("SELECT * FROM users")

静态块在类加载时执行一次,适合进行复杂的静态初始化,比如读取配置文件或建立连接。

单例模式

静态成员是实现单例模式的常用方式。

class Logger {
  private static instance: Logger
  private logs: string[] = []

  private constructor() {}

  static getInstance(): Logger {
    if (!Logger.instance) {
      Logger.instance = new Logger()
    }
    return Logger.instance
  }

  log(message: string): void {
    const timestamp = new Date().toISOString()
    this.logs.push(`[${timestamp}] ${message}`)
    console.log(`[${timestamp}] ${message}`)
  }

  getLogs(): string[] {
    return [...this.logs]
  }
}

const logger1 = Logger.getInstance()
const logger2 = Logger.getInstance()

logger1.log("启动应用")
logger2.log("加载配置")

console.log(logger1 === logger2)
console.log(logger1.getLogs())

构造函数是私有的,外部无法直接创建实例。getInstance 静态方法返回唯一的实例,确保全局只有一个 Logger。

工厂方法

静态方法常用作工厂方法,根据参数创建不同的实例。

interface Animal {
  speak(): void
}

class Dog implements Animal {
  speak(): void {
    console.log("汪汪汪")
  }
}

class Cat implements Animal {
  speak(): void {
    console.log("喵喵喵")
  }
}

class AnimalFactory {
  static create(type: string): Animal {
    switch (type) {
      case "dog":
        return new Dog()
      case "cat":
        return new Cat()
      default:
        throw new Error(`未知动物类型: ${type}`)
    }
  }
}

const dog = AnimalFactory.create("dog")
const cat = AnimalFactory.create("cat")

dog.speak()
cat.speak()

AnimalFactory.create 是静态工厂方法,根据类型参数创建对应的动物实例。

常量定义

静态只读属性常用于定义常量。

class HttpStatus {
  static readonly OK = 200
  static readonly CREATED = 201
  static readonly BAD_REQUEST = 400
  static readonly UNAUTHORIZED = 401
  static readonly FORBIDDEN = 403
  static readonly NOT_FOUND = 404
  static readonly INTERNAL_SERVER_ERROR = 500

  static getMessage(code: number): string {
    const messages: Record<number, string> = {
      [HttpStatus.OK]: "成功",
      [HttpStatus.CREATED]: "已创建",
      [HttpStatus.BAD_REQUEST]: "错误请求",
      [HttpStatus.UNAUTHORIZED]: "未授权",
      [HttpStatus.FORBIDDEN]: "禁止访问",
      [HttpStatus.NOT_FOUND]: "未找到",
      [HttpStatus.INTERNAL_SERVER_ERROR]: "服务器错误"
    }
    return messages[code] || "未知状态"
  }
}

console.log(HttpStatus.OK)
console.log(HttpStatus.getMessage(404))

HTTP 状态码定义为静态只读属性,配合静态方法使用,代码更加清晰易读。

静态成员的继承

静态成员可以被继承,子类可以访问和重写父类的静态成员。

class BaseRepository {
  static tableName: string = "base"

  static findById(id: number): any {
    console.log(`从 ${this.tableName} 表查询 ID: ${id}`)
    return { id }
  }
}

class UserRepository extends BaseRepository {
  static tableName: string = "users"

  static findByEmail(email: string): any {
    console.log(`从 ${this.tableName} 表查询邮箱: ${email}`)
    return { id: 1, email }
  }
}

console.log(UserRepository.tableName)
console.log(UserRepository.findById(1))
console.log(UserRepository.findByEmail("test@example.com"))

UserRepository 继承了 BaseRepository 的静态方法,并重写了 tableName。注意静态方法中使用 this 指向调用的类。

小结

静态成员属于类本身,通过类名直接访问。它们适合定义工具方法、常量、单例和工厂方法。静态成员不能访问实例成员,因为它们不依赖于实例。合理使用静态成员可以让代码更加简洁,避免创建不必要的实例。