在 TypeScript 编写前端代码时,遇到 TypeError: Property 'XXX' is protected and only accessible within class 'XXX' and its subclasses
错误是常见的问题。这个错误信息表明,我们试图在一个类或其子类以外的地方访问一个受保护的属性。
这篇文章将介绍 TypeScript 中 protected
属性的概念,以及如何使用不同的类继承方式来解决这个错误。
什么是 protected 属性
在 TypeScript 中,有三种属性的可见性修饰符:public
、private
和 protected
。其中,public
表示属性是公共的,可以在任何地方访问;private
表示属性是私有的,只能在类的内部访问;而 protected
表示属性是受保护的,可以在类的内部和其子类中访问,但不能在类的外部访问。
下面是一个使用 protected
属性的例子:
// javascriptcn.com 代码示例 class Person { protected name: string; constructor(name: string) { this.name = name; } } class Employee extends Person { private department: string; constructor(name: string, department: string) { super(name); this.department = department; } public getDetails(): string { return `Name: ${this.name} Department: ${this.department}`; } } const employee1 = new Employee('Alice', 'HR'); employee1.name; // Error: Property 'name' is protected and only accessible within class 'Person' and its subclasses. employee1.getDetails(); // Name: Alice Department: HR
在上面的例子中,Person
类中定义了一个 protected
属性 name
,表示一个人的名字,而 Employee
类继承自 Person
类,并在其中定义了一个 private
属性 department
,表示一个雇员的部门。Employee
类还定义了一个公共方法 getDetails()
,用于返回雇员的名字和部门。
注意到,由于 name
属性是受保护的,所以在 Employee
类的实例中无法直接访问该属性。
TypeError 的原因分析
在 TypeScript 中,当我们尝试在类或其子类以外的地方访问受保护的属性,会受到 TypeError
错误的提示。这是因为 protected
属性只能在类的内部和其子类中访问,而不能在类的外部访问。
例如,假设我们有以下代码:
// javascriptcn.com 代码示例 class Person { protected name: string; constructor(name: string) { this.name = name; } } const person1 = new Person('Alice'); console.log(person1.name); // Error: Property 'name' is protected and only accessible within class 'Person' and its subclasses.
在这个例子中,我们创建了一个 Person
对象 person1
,并在其外部尝试访问 name
属性。由于 name
属性是受保护的,因此无法在类的外部访问,从而导致了 TypeError
错误。
解决 TypeError 的方法
要解决 TypeError
错误,我们需要在 TypeScript 中使用不同的类继承方式。
使用 public
属性
一个简单的解决方法是将 name
属性从 protected
修改为 public
,这样就可以在类的外部访问该属性了。
// javascriptcn.com 代码示例 class Person { public name: string; constructor(name: string) { this.name = name; } } const person1 = new Person('Alice'); console.log(person1.name); // Alice
然而,修改属性的可见性修饰符可能会破坏类的封装性和安全性,因此使用 public
属性并不总是理想的解决方法。
使用 Getter 和 Setter 方法
另一种解决方式是使用 Getter 和 Setter 方法。Getter 方法用于获取属性的值,Setter 方法用于设置属性的值。
// javascriptcn.com 代码示例 class Person { protected _name: string; constructor(name: string) { this._name = name; } public get name(): string { return this._name; } public set name(newName: string) { this._name = newName; } } class Employee extends Person { private _department: string; constructor(name: string, department: string) { super(name); this._department = department; } public getDetails(): string { return `Name: ${this._name} Department: ${this._department}`; } } const employee1 = new Employee('Alice', 'HR'); console.log(employee1.name); // Alice employee1.name = 'Bob'; console.log(employee1.getDetails()); // Name: Bob Department: HR
在这个例子中,我们使用 _name
代替了 name
属性,并定义了一个公共的 Getter 方法 name()
和 Setter 方法 name(newName: string)
。通过 Getter 和 Setter 方法,我们可以在类中自定义获取和设置属性值的行为,以达到更好的安全性和封装性。
使用工厂方法
另一个解决方式是使用工厂方法。工厂方法是一种通过实例化类并返回一个新实例来隐藏类的构造函数的方法。通过工厂方法,我们可以控制访问对象的构造方式,从而更容易地控制对象属性的可见性。
// javascriptcn.com 代码示例 class Person { protected name: string; constructor(name: string) { this.name = name; } } class Employee extends Person { private department: string; constructor(name: string, department: string) { super(name); this.department = department; } public getDetails(): string { return `Name: ${this.name} Department: ${this.department}`; } public static create(name: string, department: string) { return new Employee(name, department); } } const employee1 = Employee.create('Alice', 'HR'); console.log(employee1.getDetails()); // Name: Alice Department: HR console.log(employee1.name); // Error: Property 'name' is protected and only accessible within class 'Person' and its subclasses.
在这个例子中,我们定义了一个静态方法 create()
,用于创建 Employee
对象。这个静态方法可以在类的内部访问 Person
类的 name
属性,并返回一个包含私有属性的新实例。由于 Employee.create()
方法是在类的内部定义的,因此可以访问受保护的 Person
属性。而在类外部访问 employee1.name
属性则会触发 TypeError
错误。
总结
在 TypeScript 中,当我们尝试访问受保护的属性时,会受到 TypeError
错误的提示。为了解决这个错误,我们可以使用不同的类继承方式,包括使用 public
属性、Getter 和 Setter 方法、以及工厂方法。
由于 protected
属性具有一定的访问限制,因此我们应该根据实际情况选择最适合的解决方法,以保证类的封装性和安全性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/652cb15e7d4982a6ebe50492