开创云网站建设支持,wordpress app模板下载失败,模板网传奇手游,设计软件基础课程学什么TypeScript 中的类是用于创建对象的蓝图。它们允许你对现实世界中的实体进行建模#xff0c;封装数据#xff0c;并实现面向对象编程的特性#xff0c;如继承、多态和方法重写。TypeScript 类提供了静态类型检查#xff0c;确保属性和方法被正确定义和使用。
一、认识类
…TypeScript 中的类是用于创建对象的蓝图。它们允许你对现实世界中的实体进行建模封装数据并实现面向对象编程的特性如继承、多态和方法重写。TypeScript 类提供了静态类型检查确保属性和方法被正确定义和使用。
一、认识类
TypeScript 类是创建对象的蓝图它封装了属性数据和方法行为以促进代码的组织性、可复用性和可读性。
支持继承允许一个类扩展另一个类并重用其功能。提供访问修饰符public、private、protected用于控制成员的访问权限并实现封装。
例如
class Person {name: string; // 姓名age: number; // 年龄constructor(name: string, age: number) {this.name name; // 初始化姓名this.age age; // 初始化年龄}introduce(): string {// 返回一段介绍自己的字符串return Hi, my name is ${this.name} and I am ${this.age} years old.;}
}const person1 new Person(Alice, 25); // 创建一个名为 Alice、年龄为 25 的对象
console.log(person1.introduce()); // 输出介绍信息
Person 类定义了 name 和 age 属性使用构造函数进行初始化并包含一个 introduce 方法用于返回问候信息。通过该类创建了一个对象 person1并调用 introduce 方法输出个性化的消息。
输出
Hi, my name is Alice and I am 25 years old.
(一) TypeScript 类的关键组成部分
方法Methods在类中定义的函数用于执行特定操作。构造函数Constructors当从类创建对象时自动调用的特殊方法。构造函数用于初始化类的属性。属性Properties与类的实例相关联的变量。继承Inheritance可以基于已有类创建新类实现代码复用和功能扩展。
(二) 访问修饰符Access Modifiers
public属性和方法可从类外部访问。private限制只能在类的内部访问。protected允许在类及其子类中访问。
(三) TypeScript 中的构造函数
构造函数是类中的一个特殊方法在创建类实例时会自动调用。其主要作用是初始化当前实例的属性。在 TypeScript 中构造函数允许我们设置对象的初始状态。
class Person {constructor(public name: string, public age: number) {// 初始化属性}
}const john new Person(Uday, 20);
console.log(Name: ${john.name}, Age: ${john.age});
输出
Name: Uday, Age: 20
(四) TypeScript 中的对象
对象是类的一个实例它包含一组键值对。值可以是标量值如数字、字符串、函数甚至是其他对象的数组。
1. 语法
let obj {key1: value1,key2: value2,// ...
};
2. 注意事项
一般推荐使用点表示法语法更清晰。当属性名是变量或者包含特殊字符时可以使用方括号表示法。
这两种方式都能访问类的属性和方法取决于使用场景。
// 访问属性
obj.field_name // 使用点表示法
obj[field_name] // 使用方括号表示法// 访问方法
obj.function_name() // 使用点表示法调用方法
obj[function_name]() // 使用方括号表示法调用方法
3. 简单对象
Person 类具有通过构造函数设置的 name 和 age 属性。它包含一个 greet 方法用于输出包含这些详细信息的问候语。嵌套类实例如 person可以访问类中定义的属性和方法。
class Person {name: string;age: number;constructor(name: string, age: number) {this.name name;this.age age;}greet() {console.log(Hello, Im ${this.name} and Im ${this.age} years old.);}
}const person new Person(Rahul, 22);
console.log(person.name); // 访问属性
person.greet(); // 访问方法
输出
Rahul
Hello, Im Rahul and Im 22 years old.
(五) 场景示例
1. 管理银行账户
// 定义一个银行账户类
class BankAccount {accountHolder: string; // 账户持有人姓名balance: number; // 当前账户余额// 构造函数初始化账户持有人姓名和初始余额constructor(accountHolder: string, initialBalance: number) {this.accountHolder accountHolder;this.balance initialBalance;}// 存款方法将金额加到账户余额上deposit(amount: number): void {this.balance amount;}// 获取当前余额返回格式化字符串getBalance(): string {return 账户持有人 {this.accountHolder} 的余额为 $${this.balance};}
}// 创建一个银行账户实例初始余额为 500
const account new BankAccount(Felix Lu, 500);// 存入 200 元
account.deposit(200);// 输出当前余额
console.log(account.getBalance());
BankAccount 类允许创建账户、存入资金和查询余额。account.deposit(200) 会将 200 元添加到初始余额 500 元中 而 getBalance 会显示更新后的账户余额。
输出
账户持有人 Felix Lu 的余额为 700
2. 表示一个矩形
class Rectangle {width: number;height: number;constructor(width: number, height: number) {this.width width;this.height height;}calculateArea(): number {return this.width * this.height;}
}const rect new Rectangle(10, 5);
console.log(矩形的面积为: ${rect.calculateArea()});
Rectangle 类通过其宽度和高度来计算矩形的面积。在 rectangle 对象上调用 calculateArea() 方法以计算面积。
输出
矩形的面积为: 50
二、构造函数参数
TypeScript 中的 ConstructorParametersType 工具类型用于从构造函数类型 Type 中提取其参数类型。它通过确保使用正确的构造函数参数类型来增强类型安全性从而使函数在创建实例时能够使用构造函数所期望的精确类型。
(一) 语法
type ConstructorParametersType ConstructorParametersType;
参数说明
ConstructorParametersType表示构造函数参数类型的类型名。Type你希望从中提取参数类型的构造函数类型。
(二) 场景示例
1. 提取CourseOrder类的构造函数参数类型
在这个例子中我们定义了一个名为 CourseOrder 的类其构造函数接受两个字符串参数。通过使用 ConstructorParameterstypeof CourseOrder我们提取了构造函数的参数类型。然后我们创建了一个 createCourseOrder 函数利用这些类型来实例化 CourseOrder 对象并传入不同的参数值。
// 定义一个类及其构造函数
class CourseOrder {constructor(name: string, course: string) {this.name name;this.course course;}name: string;course: string;
}// 提取构造函数的参数类型
type CourseOrderConstructorParams ConstructorParameterstypeof CourseOrder;// 创建一个函数用于创建该类的实例
function createCourseOrder(...params: CourseOrderConstructorParams): CourseOrder {return new CourseOrder(...params);
}const instance1 createCourseOrder(FelixLu, Java);
const instance2 createCourseOrder(Raink, Python);console.log(instance1);
console.log(instance2);
输出
CourseOrder { name: FelixLu, course: Java }
CourseOrder { name: Raink, course: Python }
2. 提取 Rectangle 类的构造函数参数类型
在这个示例中我们创建了一个 Rectangle 类其构造函数接受两个数字参数宽度和高度。通过使用 ConstructorParameterstypeof Rectangle我们获取了参数类型 [number, number]。然后我们使用这些类型定义了一个 createRectangle 函数用于生成具有不同尺寸的 Rectangle 实例。
// 定义一个类及其构造函数
class Rectangle {constructor(public width: number, public height: number) { }
}// 提取构造函数的参数类型
type RectangleConstructorParams ConstructorParameterstypeof Rectangle;// 创建一个函数用于实例化该类
function createRectangle(...params: RectangleConstructorParams): Rectangle {return new Rectangle(...params);
}const rect1 createRectangle(5, 10);
const rect2 createRectangle(8, 6);console.log(rect1);
console.log(rect2);
输出
Rectangle { width: 5, height: 10 }
Rectangle { width: 8, height: 6 }
三、访问修饰符
在 TypeScript 中访问修饰符用于控制类成员如属性和方法的可见性和访问权限符合面向对象编程中封装和信息隐藏的原则。
public公共成员可以从任何地方访问如果未指定访问修饰符默认即为 public。private私有成员只能在定义它的类内部访问。protected受保护成员可以在定义它的类及其子类中访问。
class Animal {public name: string; // 公共属性可以被外部访问private age: number; // 私有属性只能在类内部访问protected species: string; // 受保护属性可以在子类中访问constructor(name: string, age: number, species: string) {this.name name;this.age age;this.species species;}public getInfo(): string {return ${this.name} 是一只 ${this.species}。;}// 添加 getAge 方法用于访问私有属性 agepublic getAge(): number {return this.age;}
}class Dog extends Animal {constructor(name: string, age: number) {super(name, age, 狗);}public getDetails(): string {// 通过 getAge 方法访问私有属性 agereturn ${this.name} 是一只 ${this.species}年龄是 ${this.getAge()} 岁。;}
}const myDog new Dog(巴迪, 3);
console.log(myDog.name); // 可访问
console.log(myDog.getInfo()); // 可访问
console.log(myDog.getDetails()); // 可访问
name 是 public公共的可以从任何地方访问。age 是 private私有的只能在 Animal 类内部访问。species 是 protected受保护的可以在 Animal 类及其子类 Dog 中访问。
输出
巴迪
巴迪 是一只 狗。
巴迪 是一只 狗年龄是 3 岁。
(一) 访问修饰符的类型
1. 公共访问修饰符
public 修饰符允许类的成员在任何地方都可以访问。如果没有指定访问修饰符所有类成员默认都是 public。
class Animal {public name: string;constructor(name: string) {this.name name;}public makeSound(): void {console.log(${this.name} 发出声音。);}
}const dog new Animal(京巴);
console.log(dog.name); // 可访问
dog.makeSound(); // 可访问
name 和 makeSound 是 public 的允许从类的外部访问。我们可以创建 Animal 类的实例并直接访问它的 name 属性和 makeSound 方法。
输出
京巴
京巴 发出声音。
2. 私有访问修饰符
private 修饰符限制对类成员的访问使其只能在定义它们的类内部访问。这确保了封装性保护了对象的内部状态。
class Person {private ssn: string;constructor(ssn: string) {this.ssn ssn;}public getSSN(): string {return this.ssn;}
}const person new Person(123-45-6789);
console.log(person.getSSN());
// console.log(person.ssn); // 这里会报错因为 ssn 是私有的不能在类外访问
ssn 是私有的防止在类外部直接访问。公共方法 getSSN 提供对私有 ssn 属性的受控访问。
输出
123-45-6789
3. 受保护的访问修饰符Protected Access Modifier
protected 关键字用于声明一个类成员使其可以被定义它的类以及该类的任意子类访问但不能在类的外部访问。 当你希望某个类的成员可以在其派生类中访问但不希望被外部直接访问时这种修饰符非常有用。
class User {protected age: number; // 受保护的属性只能在类和子类中访问constructor(age: number) {this.age age;}
}class Employee extends User {public getRetirementAge(): number {return this.age 65; // 在子类中访问受保护属性}
}const employee new Employee(30);
console.log(employee.getRetirementAge()); // 输出95
//console.log(employee.age); // 无法访问受保护属性编译错误
age 是受保护的protected这意味着它可以在 User 类以及其子类 Employee 中访问。尝试从 Employee 的实例中直接访问 age 会导致错误因为 protected 成员不能在类外部被访问。
输出
95
(二) 最佳实践
在 TypeScript 中使用访问修饰符的最佳实践如下
明确指定访问修饰符始终为类的成员显式声明 public、private 或 protected以增强代码的可读性和可维护性。封装类成员使用 private 或 protected 来限制对类属性和方法的访问从而隐藏内部实现细节提高代码的封装性和安全性。从最小可见性开始优先使用 private 修饰类成员只有在需要与子类或外部交互时再逐步提升到 protected 或 public以最大限度地保持封装性。
四、抽象类
在 在 TypeScript 中抽象类作为其他类的基础模板不能被直接实例化。
它可以包含没有实现的抽象方法这些方法必须由任何子类进行具体实现。此外抽象类还可以包含具有实现的具体方法、属性以及其他成员。
abstract class Animal {abstract makeSound(): void; // 抽象方法子类必须实现move(): void {console.log(移动中...);}
}class Dog extends Animal {makeSound(): void {console.log(汪汪);}
}const myDog new Dog();
myDog.makeSound(); // 输出汪汪
myDog.move(); // 输出移动中...
Animal 类被声明为抽象类包含一个未实现的抽象方法 makeSound()以及一个带有实现的具体方法 move()。Dog 类继承自 Animal并为 makeSound() 方法提供了具体的实现。创建了 Dog 类的一个实例并调用了 makeSound() 和 move() 方法展示了抽象方法与具体方法的使用方式。
输出
汪汪
移动中...
(一) 抽象类的关键特性
不能被实例化抽象类无法直接创建实例任何试图实例化抽象类的操作都会在编译阶段失败。抽象方法抽象类中可以声明没有实现的方法称为抽象方法。所有继承该类的子类必须实现这些方法。具体方法抽象类也可以包含完整实现的方法这些方法可以被子类继承并直接使用。可以包含属性和构造函数尽管抽象类本身不能实例化但它可以拥有构造函数和属性通常用于初始化共有属性或设置通用逻辑供子类继承使用。支持多态性通过抽象类可以实现多态允许将其子类视作抽象类类型进行操作增强代码的灵活性。
(二) 抽象类的应用场景
定义统一接口抽象类可以作为多个相关类的统一接口使所有子类遵循统一的结构提升代码的可读性与维护性。代码复用抽象类中定义的通用方法和属性可以被子类继承减少代码重复提高开发效率。强制子类实现方法通过抽象方法抽象类可以强制子类实现具体的功能确保不同子类根据自身需求提供不同的实现方式。封装共享逻辑将多个子类之间通用的逻辑集中在抽象类中实现便于后期集中维护和修改提升系统的一致性与可扩展性。
(三) 场景示例
1. 带有抽象属性的抽象类
abstract class Person {abstract name: string;display(): void {console.log(this.name);}
}class Employee extends Person {name: string;empCode: number;constructor(name: string, code: number) {super();this.name name;this.empCode code;}
}const emp new Employee(FelixLu, 100);
emp.display();
Person 抽象类声明了一个抽象属性 name 和一个具体方法 display()用于打印 name。Employee 类继承自 Person实现了 name 属性并添加了 empCode 属性。创建了一个名为 James、编码为 100 的 Employee 实例并调用 display() 方法输出 name。
输出
FelixLu
2. 带有抽象方法的抽象类
abstract class Shape {abstract getArea(): number;printArea(): void {console.log(面积是 ${this.getArea()}。);}
}class Circle extends Shape {radius: number;constructor(radius: number) {super();this.radius radius;}getArea(): number {return Math.PI * this.radius * this.radius;}
}const circle new Circle(5);
circle.printArea();
Shape 抽象类包含一个抽象方法 getArea() 和一个具体方法 printArea()用于打印面积。Circle 类继承自 Shape实现了 getArea() 方法来计算圆的面积。创建了一个半径为 5 的 Circle 实例并调用 printArea() 方法显示面积。
输出
The area is 78.53981633974483.
(四) 最佳实践
TypeScript 中使用抽象类的最佳实践
使用抽象类封装共享功能当多个相关类具有共同的行为时定义抽象类来封装这些共享功能有助于代码复用和保持一致性。为必须实现的方法定义抽象方法如果所有子类都必须实现某些方法应在基类中将它们声明为抽象方法从而强制子类提供具体实现。避免直接实例化抽象类抽象类不应被直接实例化确保只实例化其子类以维护设计模式的完整性。
五、继承
继承是面向对象编程OOP中的一个基本概念。它允许一个类继承另一个类的属性和方法。继承的类称为子类被继承属性和方法的类称为父类。继承实现了代码复用使得一个类可以利用已有类的功能而无需重新编写代码。
(一) TypeScript中的继承
JavaScript使用的是原型继承而不是像Java或C那样的经典继承。TypeScript采用基于类的继承这其实是对原型继承的语法糖。TypeScript只支持单继承和多级继承。在TypeScript中类通过使用 extends 关键字来继承另一个类。
1. 语法
class ChildClass extends ParentClass {// 方法和属性
}
2. 例子
在下面这个例子里类 Car 继承了 Vehicle 类的 honk() 方法。通过这种方式Car 类可以重用其父类的方法。
class Vehicle {honk(): void {console.log(车辆鸣笛);}
}class Car extends Vehicle {display(): void {console.log(这是一辆汽车);}
}let car new Car();
car.honk(); // 输出车辆鸣笛
car.display(); // 输出这是一辆汽车
输出
车辆鸣笛
这是一辆汽车
(二) super 关键字
TypeScript 使用 super 关键字调用父类的属性和方法。super 关键字的主要用途包括
调用父类的构造函数调用父类的方法
下面举一个 Person 类和继承 Person 类的 Employee 类的例子。
class Person {constructor(private firstName: string, private lastName: string) {this.firstName firstName;this.lastName lastName;}getName(): string {return 我是 ${this.firstName} ${this.lastName}.;}
}
class Employee extends Person {constructor(firstName: string,lastName: string,private jobTitle: string) {// 调用 Person 类的构造函数super(firstName, lastName);}displayInfo(): void {console.log(super.getName()); // 调用父类的方法console.log(我的职位是 ${this.jobTitle});}
}
let employee new Employee(Felix, Lu, Web 开发工程师);employee.displayInfo();
这里Employee 类使用 super() 调用 Person 类的构造函数来初始化 firstName 和 lastName。它还在自身的方法中通过 super 调用了 getName() 方法。
输出
我是 Felix Lu.
我的职位是 Web 开发工程师
(三) 方法重写
TypeScript 也支持方法重写。我们以 Employee 类为例该类将重写 Person 类中的方法。
1. 例子
class Person {constructor(private firstName: string, private lastName: string) {this.firstName firstName;this.lastName lastName;}displayInfo(): string {return 我是 ${this.firstName} ${this.lastName}。;}
}class Employee extends Person {constructor(firstName: string,lastName: string,private jobTitle: string) {// 调用 Person 类的构造函数super(firstName, lastName);}displayInfo(): string {return super.displayInfo() 职位是 ${this.jobTitle}。;}
}let employee new Employee(Felix, Lu, 网页开发工程师);console.log(employee.displayInfo());
输出
我是 Felix Lu。 职位是 网页开发工程师。
六、方法重写
方法重写是指在派生子类中用与基类或父类中同名且签名相同的方法重新定义该方法。这允许子类提供自己对该方法的实现可以扩展或完全替代基类中定义的行为。
(一) 基本知识
关于方法重写
子类的方法可以选择使用或不使用父类方法中定义的逻辑。若要调用基类的方法或属性可以使用 super 关键字。该关键字帮助子类访问基类的方法或属性。
当我们希望改变子类继承自父类的方法行为时方法重写尤其有用。
(二) 场景示例
1. 基本的方法重写
在此示例中我们声明了两个类。在父类中声明了一个方法随后子类使用自己的逻辑重写了该方法。
class Person {name: string;rollNumber: number;score: number;constructor(name: string, rollNumber: number, score: number) {this.name name;this.rollNumber rollNumber;this.score score;}displayDetails(): void {console.log(姓名: ${this.name}, 学号: ${this.rollNumber}, 分数: ${this.score}满分100);}
}class Student extends Person {constructor(name: string, rollNumber: number, score: number) {super(name, rollNumber, score);}displayDetails(): void {console.log(姓名: ${this.name}, 学号: ${this.rollNumber}, 分数: ${this.score}满分100);console.log(${this.name} 成绩优异...);}
}const student new Student(李明, 2, 96);
student.displayDetails();
输出
姓名: 李明, 学号: 2, 分数: 96满分100
李明 成绩优异...
2. 使用 super 调用父类方法
在此示例中我们在子类重写的方法中使用 super 关键字调用父类的方法并显示其结果。
class Person {name: string;rollNumber: number;score: number;constructor(name: string, rollNumber: number, score: number) {this.name name;this.rollNumber rollNumber;this.score score;}displayDetails(): void {console.log(姓名: ${this.name}, 学号: ${this.rollNumber}, 成绩: ${this.score} 分满分100);}
}class Student extends Person {constructor(name: string, rollNumber: number, score: number) {super(name, rollNumber, score);}displayDetails(): void {super.displayDetails();console.log(${this.name} 是一个聪明的男孩。);console.log(${this.name} 成绩很好。);}
}const student new Student(FelixLu, 2, 96);
student.displayDetails();
输出
姓名: FelixLu, 学号: 2, 成绩: 96 分满分100
FelixLu 是一个聪明的男孩。
FelixLu 成绩很好。