类和对象 Class & Object
TypeScript enhances JavaScript's object-oriented programming capabilities by adding type safety and other features. Here's a guide to classes and objects in TypeScript.
Basic Concepts
Below are the fundamental concepts of classes and objects:
类 Class
A class in TypeScript, like in Python, is a blueprint for creating objects. It defines a set of attributes (data) and methods (functions to manipulate the data).
class Dog {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
bark(): void {
console.log("Woof!");
}
}
特点 Features
- Attributes: Variables defined inside a class. They describe the state or characteristics of the objects.
- Methods: Functions defined inside a class. They describe what the objects can do.
对象 Object
An object is an instance of a class created according to the class definition. Each object has the attributes and methods defined in its class.
let roger = new Dog("Roger", 8);
console.log(roger.name); // "Roger"
console.log(roger.age); // 8
roger.bark(); // "Woof!"
特点 Features
- Instantiation: Creating an instance of a class (object).
- State: Objects maintain a state through their attributes.
- Behavior: Objects demonstrate behavior through their methods.
继承与多态 Inherit & Polymorphism
Combining inheritance and polymorphism allows for flexible and easily extendable code structures, where subclasses only need to define or modify specific behaviors.
继承 Inherit
Inheritance is a mechanism that allows one class (the subclass) to inherit attributes and methods from another class (the superclass). The subclass can add new functionalities or override some methods.
// Superclass
class Animal {
speak(): string {
return "";
}
}
// Subclasses
class Dog extends Animal {
speak(): string {
return "Woof!";
}
}
class Cat extends Animal {
speak(): string {
return "Meow!";
}
}
In this example, Animal
is a superclass, and Dog
and Cat
are subclasses inheriting from Animal
. Each subclass has its own implementation of the speak
method.
Features
- Code Reusability: Subclasses can use code from the superclass, reducing redundancy.
- Extensibility: New functionalities can be added based on the superclass.
- Hierarchy: Inheritance creates a natural hierarchy.
多态 Polymorphism
Polymorphism allows objects of different classes to respond differently to the same interface or method call.
function animalSpeak(animal: Animal): void {
console.log(animal.speak());
}
let myDog = new Dog();
let myCat = new Cat();
animalSpeak(myDog); // Outputs "Woof!"
animalSpeak(myCat); // Outputs "Meow!"
Here, animalSpeak
function accepts an Animal
type object and calls its speak
method. Due to the Dog
and Cat
classes overriding the speak
method, their response to speak
is different, illustrating polymorphism.
特点 Features
- Interface Consistency: Different objects can be treated through a common interface.
- Flexibility: Code can remain unaware of the specific types of objects.
- Extensibility: Adding new subclasses does not affect the existing classes.
封装和成员 Encapsulation and Private Members
Encapsulation and private members ensure that an object's state can only be changed through a well-defined interface, which helps maintain data integrity and reduce bugs.
封装 Encapsulation
Encapsulation is a way to restrict direct access to an object's components and at the same time allows controlling them through methods provided. This prevents the external code from accidentally altering the internal state.
class BankAccount {
private balance: number;
constructor(initialBalance: number = 0) {
this.balance = initialBalance;
}
deposit(amount: number): void {
if (amount > 0) {
this.balance += amount;
console.log(`Deposited ${amount}`);
} else {
console.log("Deposit amount must be greater than zero.");
}
}
withdraw(amount: number): void {
if (amount > 0 && amount <= this.balance) {
this.balance -= amount;
console.log(`Withdrew ${amount}`);
} else {
console.log("Withdrawal amount must be positive and not exceed the balance.");
}
}
getBalance(): number {
return this.balance;
}
}
// Usage
let account = new BankAccount(1000);
account.deposit(500);
account.withdraw(200);
console.log(`Current balance: ${account.getBalance()}`);
这个类的设计体现了封装原则:通过公共方法控制对私有属性的访问,保证了账户余额的正确性和安全性。
特点 Features
- 数据隐藏: 将类的内部状态(数据)隐藏起来,只允许通过定义好的接口访问。
- 接口提供: 提供方法(接口)来操作内部数据,而不是直接暴露数据。
- 增强安全性: 防止外部代码意外改变对象的内部状态。
公开成员 Public Members
By default all the members of a class are public in typescript that means we can access and modify them outside of the class.
私有成员 Private Members
Private members are allowed to access or modify inside the class but not allowed outside of the class.
In TypeScript, private members are defined with the private
keyword and cannot be accessed outside the class.
class Car {
private color: string;
// #color: string;
constructor(color: string) {
this.color = color;
}
getColor(): string {
return this.color;
}
private privateMethod(): void {
console.log("This is a private method");
}
}
let myCar = new Car("red");
console.log(myCar.getColor());
In this example, color
and privateMethod
are private and only accessible within the Car
class. getColor
is a public method that provides safe access to the private color
property.
特点 Features
...
保护成员 Protected Members
Protected members can be accessed or modified within the class as well as within its child classes.
class Employee {
name: string;
protected age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
class manager extends Employee {
designation: string;
constructor(name: string, age: number, designation: string) {
super(name, age);
this.designation = designation;
}
display() {
console.log(this.age);
}
modify(num: number) {
this.age = num;
}
}
let emp = new Manager("Winston", 45, "Manager");
emp.display(); // 45
emp.modify(90);
emp.display(); // 90
实例方法和静态方法 Instance Methods and Static Methods
Instance Methods
class MyClass {
value: number;
constructor(value: number) {
this.value = value;
}
instanceMethod(): string {
return `Instance method called, value = ${this.value}`;
}
}
Static Methods
Defined with the static
keyword, do not require an instance to be called, and cannot access instance-specific data.
class MyClass {
static staticMethod(): string {
return "Static method called";
}
}
实例是否能够访问 static 方法 和 attributes ?
在 TypeScript 中,类的静态方法和属性属于类本身,不属于类的实例。这意味着你不能直接通过一个类的实例来访问静态方法或属性。静态成员是通过类名本身来访问的。
举个例子:
class MyClass {
static staticAttribute: string = "I am static";
static staticMethod(): void {
console.log("This is a static method.");
}
instanceMethod(): void {
console.log("This is an instance method.");
// 你不能通过'this'关键字来调用静态方法或属性
// this.staticMethod(); // 错误
// console.log(this.staticAttribute); // 错误
// 但你可以通过类名来调用静态方法或属性
MyClass.staticMethod(); // 正确
console.log(MyClass.staticAttribute); // 正确
}
}
let myInstance = new MyClass();
myInstance.instanceMethod(); // 这将调用实例方法,实例方法内部可以访问静态方法和属性
在上面的代码中,静态方法staticMethod
和静态属性staticAttribute
可以通过类名MyClass
来访问。尽管实例方法instanceMethod
可以访问静态成员,但它必须通过类名来访问,而不是通过this
关键字。
调用静态成员的正确方式是使用类名,如MyClass.staticMethod()
,而不是使用实例,如myInstance.staticMethod()
。尝试通过实例来访问静态成员将会导致 TypeScript 编译时错误。