访问修饰符(public/private/protected)
访问修饰符(public/private/protected)
TypeScript中的访问修饰符用于控制类成员的可访问性,主要包含public
、private
和protected
三种。这些修饰符决定了类成员在类内部、子类以及类外部能否被访问。
public修饰符
public
是默认的访问修饰符,当没有显式指定修饰符时,类成员默认为public
。public
成员可以在类的内部、子类以及类的外部被访问。
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
类内部访问。外部代码只能通过deposit
和getBalance
方法来操作和查询余额。
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
在这个例子中,构造函数参数id
、name
和grade
分别使用了public
、private
和protected
修饰符,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