在本章中,我们将深入探讨如何在 Deno 中使用类和对象。JavaScript 和 TypeScript 是基于原型继承的语言,但同时也支持面向对象编程(OOP)。Deno 支持 TypeScript,因此我们可以在 Deno 应用程序中使用类和对象来构建更复杂、更具模块化和可重用性的代码。
类的定义与实例化
在 JavaScript 和 TypeScript 中,类是用于创建对象的蓝图。让我们从一个简单的类定义开始:
// www.javascriptcn.com code example
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}在上面的例子中,我们定义了一个 Person 类,它有两个属性:name 和 age。构造函数是一个特殊的方法,当使用 new 关键字创建一个新的对象实例时会自动调用。我们还定义了一个 greet 方法,该方法会在控制台上打印一条问候信息。
要实例化这个类,我们可以这样做:
const person = new Person("Alice", 30);
person.greet(); // 输出 "Hello, my name is Alice and I am 30 years old."继承与多态
在面向对象编程中,继承是一个重要的概念,它允许我们定义一个新类作为现有类的子类。子类可以继承父类的所有属性和方法,并且还可以添加新的方法或覆盖现有的方法。
让我们来看一个例子,其中我们定义了一个 Student 类,它是 Person 类的子类:
// www.javascriptcn.com code example
class Student extends Person {
grade: string;
constructor(name: string, age: number, grade: string) {
super(name, age); // 调用父类的构造函数
this.grade = grade;
}
study() {
console.log(`${this.name} is studying in grade ${this.grade}.`);
}
}
const student = new Student("Bob", 20, "Sophomore");
student.greet(); // 继承自 Person 的方法
student.study(); // Student 类特有的方法在这个例子中,Student 类继承了 Person 类,并且添加了一个新的属性 grade 和一个新方法 study()。通过调用 super(name, age),我们可以确保父类的构造函数也被正确调用。
访问修饰符
在 TypeScript 中,我们可以使用访问修饰符来控制类成员的可见性。常用的访问修饰符包括:
public:默认值,表示该成员可以从任何地方访问。private:表示该成员只能在声明它的类内部访问。protected:表示该成员可以在声明它的类及其子类内部访问。
// www.javascriptcn.com code example
class Animal {
public name: string;
private age: number;
protected habitat: string;
constructor(name: string, age: number, habitat: string) {
this.name = name;
this.age = age;
this.habitat = habitat;
}
public getAge(): number {
return this.age;
}
protected getHabitat(): string {
return this.habitat;
}
}
class Dog extends Animal {
bark() {
console.log(`${this.name} is barking!`);
}
getHabitat() { // 子类可以覆盖 protected 成员
return `This dog lives in ${super.getHabitat()}`;
}
}
const dog = new Dog("Rex", 5, "house");
console.log(dog.name); // 可以访问
// console.log(dog.age); // 错误:无法访问私有属性
console.log(dog.getAge()); // 可以通过公有方法访问
console.log(dog.getHabitat()); // 可以通过公有方法访问抽象类
抽象类是不能被实例化的类,它们通常用于定义其他类的基类。抽象类可以包含抽象方法,这些方法没有实现,只定义了签名。
// www.javascriptcn.com code example
abstract class Vehicle {
abstract startEngine(): void;
drive() {
console.log("Driving...");
}
}
class Car extends Vehicle {
startEngine() {
console.log("Car engine started.");
}
}
class Motorcycle extends Vehicle {
startEngine() {
console.log("Motorcycle engine started.");
}
}
const car = new Car();
car.startEngine();
car.drive();
const motorcycle = new Motorcycle();
motorcycle.startEngine();
motorcycle.drive();在这个例子中,Vehicle 是一个抽象类,它有一个抽象方法 startEngine()。Car 和 Motorcycle 类继承了 Vehicle 类,并实现了 startEngine() 方法。
接口
接口是定义对象结构的一种方式。它们允许我们定义对象应该具有哪些属性和方法,而不必关心具体的实现细节。
// www.javascriptcn.com code example
interface IPerson {
name: string;
age: number;
greet(): void;
}
class Teacher implements IPerson {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, I'm a teacher named ${this.name} and I'm ${this.age} years old.`);
}
}
const teacher = new Teacher("Charlie", 40);
teacher.greet();在这个例子中,我们定义了一个 IPerson 接口,它要求实现者具有 name 和 age 属性以及 greet() 方法。Teacher 类实现了 IPerson 接口。
泛型
泛型允许我们在定义类、接口或方法时使用类型参数。这使得我们可以在不指定具体类型的情况下编写更加通用和灵活的代码。
// www.javascriptcn.com code example
class Box<T> {
content: T;
constructor(content: T) {
this.content = content;
}
getContent(): T {
return this.content;
}
setContent(newContent: T): void {
this.content = newContent;
}
}
const stringBox = new Box<string>("hello");
console.log(stringBox.getContent());
const numberBox = new Box<number>(123);
console.log(numberBox.getContent());在这个例子中,我们定义了一个泛型类 Box,它可以存储任何类型的值。我们分别创建了存储字符串和数字的 Box 实例,并演示了如何获取和设置内容。
静态成员
静态成员属于类本身而不是类的实例。这意味着我们可以通过类名直接访问静态成员,而不需要创建类的实例。
// www.javascriptcn.com code example
class MathUtils {
static PI = 3.14159;
static calculateCircleArea(radius: number): number {
return MathUtils.PI * radius * radius;
}
}
console.log(MathUtils.PI);
console.log(MathUtils.calculateCircleArea(5));在这个例子中,我们定义了一个 MathUtils 类,它有两个静态成员:PI 和 calculateCircleArea 方法。我们可以通过类名 MathUtils 直接访问这两个静态成员。
总结
通过本章的学习,我们了解了如何在 Deno 应用程序中使用类和对象来构建复杂的结构。我们讨论了类的定义与实例化、继承与多态、访问修饰符、抽象类、接口、泛型以及静态成员的概念。这些知识将帮助你在实际项目中更好地组织和管理代码。