阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 访问修饰符(public/private/protected)

访问修饰符(public/private/protected)

作者:陈川 阅读数:46783人阅读 分类: TypeScript

访问修饰符(public/private/protected)

TypeScript中的访问修饰符用于控制类成员的可访问性,主要包含publicprivateprotected三种。这些修饰符决定了类成员在类内部、子类以及类外部能否被访问。

public修饰符

public是默认的访问修饰符,当没有显式指定修饰符时,类成员默认为publicpublic成员可以在类的内部、子类以及类的外部被访问。

class Person {
  public name: string;
  
  constructor(name: string) {
    this.name = name;
  }
  
  public greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

const person = new Person('Alice');
console.log(person.name); // 输出: Alice
person.greet(); // 输出: Hello, my name is Alice

在这个例子中,name属性和greet方法都是public的,因此可以在类的外部直接访问。

private修饰符

private修饰符表示成员只能在类的内部访问,不能在子类或类的外部访问。这有助于封装类的内部实现细节。

class BankAccount {
  private balance: number;
  
  constructor(initialBalance: number) {
    this.balance = initialBalance;
  }
  
  public deposit(amount: number) {
    if (amount > 0) {
      this.balance += amount;
    }
  }
  
  public getBalance(): number {
    return this.balance;
  }
}

const account = new BankAccount(1000);
account.deposit(500);
console.log(account.getBalance()); // 输出: 1500
// console.log(account.balance); // 错误: 属性'balance'是私有的,只能在类'BankAccount'中访问

这里balance属性被标记为private,因此只能在BankAccount类内部访问。外部代码只能通过depositgetBalance方法来操作和查询余额。

protected修饰符

protected修饰符表示成员可以在类内部和子类中访问,但不能在类的外部访问。这在实现继承时特别有用。

class Vehicle {
  protected speed: number = 0;
  
  protected accelerate(amount: number) {
    this.speed += amount;
  }
}

class Car extends Vehicle {
  public drive() {
    this.accelerate(10); // 可以在子类中访问protected方法
    console.log(`Driving at ${this.speed} km/h`); // 可以在子类中访问protected属性
  }
}

const car = new Car();
car.drive(); // 输出: Driving at 10 km/h
// car.accelerate(5); // 错误: 属性'accelerate'受保护,只能在类'Vehicle'及其子类中访问
// console.log(car.speed); // 错误: 属性'speed'受保护,只能在类'Vehicle'及其子类中访问

Vehicle类中的speed属性和accelerate方法都是protected的,因此可以在Car子类中访问,但不能在类的外部直接访问。

构造函数中的访问修饰符

在TypeScript中,构造函数参数也可以使用访问修饰符,这实际上是声明和初始化类成员的快捷方式。

class Student {
  constructor(public id: number, private name: string, protected grade: string) {}
  
  public getInfo() {
    return `ID: ${this.id}, Name: ${this.name}, Grade: ${this.grade}`;
  }
}

const student = new Student(1, 'Bob', 'A');
console.log(student.id); // 输出: 1
// console.log(student.name); // 错误: 属性'name'是私有的,只能在类'Student'中访问
// console.log(student.grade); // 错误: 属性'grade'受保护,只能在类'Student'及其子类中访问
console.log(student.getInfo()); // 输出: ID: 1, Name: Bob, Grade: A

在这个例子中,构造函数参数idnamegrade分别使用了publicprivateprotected修饰符,TypeScript会自动将这些参数声明为类成员并初始化。

访问修饰符与继承

访问修饰符在继承关系中起着重要作用,特别是protected成员在子类中的可见性。

class Animal {
  private secret = "I'm an animal";
  protected name: string;
  
  constructor(name: string) {
    this.name = name;
  }
}

class Dog extends Animal {
  private breed: string;
  
  constructor(name: string, breed: string) {
    super(name);
    this.breed = breed;
  }
  
  public getDescription() {
    return `${this.name} is a ${this.breed}`; // 可以访问protected的name
    // return this.secret; // 错误: 属性'secret'是私有的,只能在类'Animal'中访问
  }
}

const dog = new Dog('Buddy', 'Golden Retriever');
console.log(dog.getDescription()); // 输出: Buddy is a Golden Retriever
// console.log(dog.name); // 错误: 属性'name'受保护,只能在类'Animal'及其子类中访问
// console.log(dog.breed); // 错误: 属性'breed'是私有的,只能在类'Dog'中访问

访问修饰符与接口实现

当类实现接口时,访问修饰符必须与接口定义兼容。接口中的所有成员默认都是public的。

interface ILogger {
  log(message: string): void;
}

class ConsoleLogger implements ILogger {
  public log(message: string) {
    console.log(message);
  }
  
  private internalLog(details: string) {
    console.debug(`[DEBUG] ${details}`);
  }
}

const logger = new ConsoleLogger();
logger.log("This is a public message"); // 输出: This is a public message
// logger.internalLog("Debug info"); // 错误: 属性'internalLog'是私有的,只能在类'ConsoleLogger'中访问

访问修饰符与静态成员

访问修饰符也可以应用于静态成员,控制静态成员的可见性。

class Configuration {
  private static instance: Configuration;
  public static version: string = "1.0";
  
  private constructor() {}
  
  public static getInstance(): Configuration {
    if (!Configuration.instance) {
      Configuration.instance = new Configuration();
    }
    return Configuration.instance;
  }
}

console.log(Configuration.version); // 输出: 1.0
const config = Configuration.getInstance();
// const config2 = new Configuration(); // 错误: 类'Configuration'的构造函数是私有的

访问修饰符与抽象类

在抽象类中,访问修饰符可以控制抽象成员的可见性。

abstract class Shape {
  protected abstract getArea(): number;
  
  public displayArea() {
    console.log(`Area: ${this.getArea()}`);
  }
}

class Circle extends Shape {
  constructor(private radius: number) {
    super();
  }
  
  protected getArea(): number {
    return Math.PI * this.radius * this.radius;
  }
}

const circle = new Circle(5);
circle.displayArea(); // 输出: Area: 78.53981633974483
// circle.getArea(); // 错误: 属性'getArea'受保护,只能在类'Shape'及其子类中访问

访问修饰符与getter/setter

访问修饰符可以应用于getter和setter方法,控制属性的读写权限。

class Temperature {
  private _celsius: number = 0;
  
  public get celsius(): number {
    return this._celsius;
  }
  
  public set celsius(value: number) {
    if (value < -273.15) {
      throw new Error("Temperature cannot be below absolute zero");
    }
    this._celsius = value;
  }
  
  public get fahrenheit(): number {
    return this._celsius * 9/5 + 32;
  }
  
  private set fahrenheit(value: number) {
    this._celsius = (value - 32) * 5/9;
  }
}

const temp = new Temperature();
temp.celsius = 25;
console.log(temp.celsius); // 输出: 25
console.log(temp.fahrenheit); // 输出: 77
// temp.fahrenheit = 77; // 错误: 属性'fahrenheit'是私有的,只能在类'Temperature'中访问

访问修饰符与readonly

readonly修饰符可以与访问修饰符一起使用,创建只读属性。

class Constants {
  public static readonly PI = 3.14159;
  private static readonly SECRET_KEY = "abc123";
  
  public static getSecretHash(): string {
    return this.SECRET_KEY + "hash";
  }
}

console.log(Constants.PI); // 输出: 3.14159
// Constants.PI = 3.14; // 错误: 无法分配到"PI",因为它是只读属性
console.log(Constants.getSecretHash()); // 输出: abc123hash
// console.log(Constants.SECRET_KEY); // 错误: 属性'SECRET_KEY'是私有的,只能在类'Constants'中访问

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌