【TypeScript】面向对象

news/2024/9/29 9:01:10 标签: typescript, javascript, 前端

文章目录

  • 面向对象
    • TypeScript 接口详解
      • 接口的基本定义
        • 示例
      • 联合类型和接口
        • 示例
      • 接口和数组
        • 示例
      • 接口继承
        • 单接口继承
        • 多接口继承
    • TypeScript 类详解
      • 类的基本定义
      • 创建类
      • 创建实例化对象
      • 类的继承
        • 示例
      • 方法重写
        • 示例
      • static 关键字
        • 示例
      • instanceof 运算符
        • 示例
      • 访问控制修饰符
        • 示例
      • 类与接口
        • 示例
    • TypeScript 对象详解
      • 对象的基本定义
        • 访问对象的值
      • TypeScript 类型模板
      • 传递对象作为函数参数
        • 示例
    • TypeScript 泛型详解
      • 泛型的优势
      • 泛型标识符
      • 泛型函数
      • 泛型接口
      • 泛型类
      • 泛型约束
      • 泛型与默认值
      • 泛型函数例子
        • 代码说明:
        • 输出示例:
    • 学习总结

面向对象

TypeScript 接口详解

接口是 TypeScript 中用于定义对象结构的工具,它提供了一组方法和属性的抽象声明,确保实现这些接口的类或对象遵循相应的结构。

接口的基本定义

TypeScript 接口的基本定义如下:

typescript">interface InterfaceName {
}
示例

下面是一个关于车辆的接口示例:

typescript">interface IVehicle {
    brand: string;
    model: string;
    year: number;
    start: () => string;
}

const car: IVehicle = {
    brand: "Toyota",
    model: "Camry",
    year: 2020,
    start: (): string => { return "Engine started!"; }
};

console.log("Car Details:");
console.log(`Brand: ${car.brand}`);
console.log(`Model: ${car.model}`);
console.log(`Year: ${car.year}`);
console.log(car.start());

输出结果:

Car Details:
Brand: Toyota
Model: Camry
Year: 2020
Engine started!

联合类型和接口

接口支持联合类型,允许某个属性接受多种类型的值。

示例
typescript">interface RequestOptions {
    url: string;
    method: string;
    headers?: { [key: string]: string };
    body?: string | object | (() => string);
}

// 使用字符串作为 body
let request: RequestOptions = { url: "https://api.example.com", method: "GET" ,body:"this is body"};
console.log(request.body);


// 使用对象作为 body
request = { url: "https://api.example.com", method: "POST", body: { name: "John" } };
console.log(request.body);

// 使用函数作为 body
request = { url: "https://api.example.com", method: "PUT", body: () => "Update data" };
console.log((request.body as () => string)());

输出结果:

undefined
{ name: 'John' }
Update data

接口和数组

接口中可以定义数组的索引和元素类型。

示例
typescript">interface StringList {
    [index: number]: string;
}

// 正确示例
const fruits: StringList = ["Apple", "Banana", "Cherry"];
console.log(fruits);

// 错误示例:元素类型不匹配
// const fruits: StringList = ["Apple", 1, "Cherry"]; // 会报错

接口继承

接口可以通过其他接口进行扩展,TypeScript 允许单接口或多接口的继承。

单接口继承
typescript">interface Employee {
    id: number;
    name: string;
}

interface Manager extends Employee {
    department: string;
}

const manager: Manager = {
    id: 1,
    name: "Alice",
    department: "Sales"
};

console.log(`Manager: ${manager.name}, Department: ${manager.department}`);

输出结果:

Manager: Alice, Department: Sales
多接口继承
typescript">interface IAddress {
    street: string;
    city: string;
}

interface IContact {
    email: string;
    phone: string;
}

interface IUser extends IAddress, IContact {
    username: string;
}

const user: IUser = {
    username: "john_doe",
    street: "123 Main St",
    city: "New York",
    email: "john@example.com",
    phone: "123-456-7890"
};

console.log(`User: ${user.username}, Email: ${user.email}`);

输出结果:

User: john_doe, Email: john@example.com

TypeScript 类详解

TypeScript 是一种面向对象的 JavaScript,它允许我们使用类、接口等特性来组织代码。类定义了对象的共同属性和方法。

类的基本定义

TypeScript 中类的定义格式如下:

typescript">class ClassName {
    // 类的属性和方法
}

类的定义包括以下几个部分:

  • 字段:类中声明的变量,表示对象的数据。
  • 构造函数:在实例化类时调用,用于初始化对象。
  • 方法:类中定义的功能,可以被对象调用。

创建类

以下示例展示了一个 Book 类,包含字段 titleauthor,并通过构造函数初始化这些字段。

typescript">class Book {
    title: string;
    author: string;

    constructor(title: string, author: string) {
        this.title = title;
        this.author = author;
    }

    displayInfo(): void {
        console.log(`书名: ${this.title}, 作者: ${this.author}`);
    }
}

创建实例化对象

使用 new 关键字来实例化类的对象:

typescript">const myBook = new Book("1984", "George Orwell");

// 访问字段
console.log(`书名: ${myBook.title}`);

// 调用方法
myBook.displayInfo();

输出结果:

书名: 1984
书名: 1984, 作者: George Orwell

类的继承

TypeScript 支持类的继承,子类可以从父类继承属性和方法。

示例
typescript">class Vehicle {
    brand: string;

    constructor(brand: string) {
        this.brand = brand;
    }

    displayBrand(): void {
        console.log(`品牌: ${this.brand}`);
    }
}

class Car extends Vehicle {
    model: string;

    constructor(brand: string, model: string) {
        super(brand); // 调用父类构造函数
        this.model = model;
    }

    displayInfo(): void {
        this.displayBrand();
        console.log(`车型: ${this.model}`);
    }
}

const myCar = new Car("Toyota", "Corolla");
myCar.displayInfo();

输出结果:

品牌: Toyota
车型: Corolla

方法重写

子类可以重写父类的方法,以实现特定功能。

示例
typescript">class Animal {
    sound(): void {
        console.log("动物发出声音");
    }
}

class Dog extends Animal {
    sound(): void {
        console.log("汪汪!");
    }
}

const myDog = new Dog();
myDog.sound(); // 输出:汪汪!

static 关键字

使用 static 关键字定义静态属性和方法,这些成员可以直接通过类名调用。

示例
typescript">class Counter {
    static count: number = 0;

    static increment(): void {
        this.count++;
        console.log(`计数器: ${this.count}`);
    }
}

Counter.increment(); // 输出:计数器: 1
Counter.increment(); // 输出:计数器: 2

instanceof 运算符

instanceof 用于检查一个对象是否为某个类的实例。

示例
typescript">class Person {}

const john = new Person();
const isPerson = john instanceof Person;

console.log(`john 是 Person 的实例吗? ${isPerson}`); // 输出:true

访问控制修饰符

TypeScript 提供了三种访问修饰符:

  • public(默认):可以在任何地方访问。
  • protected:只能在类自身及其子类中访问。
  • private:只能在定义该成员的类中访问。
示例
typescript">class User {
    public name: string;
    private password: string;

    constructor(name: string, password: string) {
        this.name = name;
        this.password = password;
    }
}

const user = new User("Alice", "123456");
console.log(user.name); // 可访问
// console.log(user.password); // 编译错误:属性 'password' 是私有的

类与接口

类可以实现接口,使用 implements 关键字。

示例
typescript">interface IAccount {
    accountNumber: number;
    balance: number;
    deposit(amount: number): void;
}

class BankAccount implements IAccount {
    accountNumber: number;
    balance: number;

    constructor(accountNumber: number, balance: number) {
        this.accountNumber = accountNumber;
        this.balance = balance;
    }

    deposit(amount: number): void {
        this.balance += amount;
        console.log(`存款: ${amount}, 余额: ${this.balance}`);
    }
}

const account = new BankAccount(123456, 1000);
account.deposit(500); // 输出:存款: 500, 余额: 1500

TypeScript 对象详解

在 TypeScript 中,对象是键值对的集合,可以包含不同类型的数据,包括标量、函数和数组。

对象的基本定义

以下是一个包含多种类型值的对象示例:

typescript">const userProfile = {
    username: "john_doe",  // 标量
    age: 30,
    greet: function() {      // 函数
        console.log(`Hello, my name is ${this.username}`);
    },
    hobbies: ["reading", "gaming"] // 数组
};

// 调用函数
userProfile.greet(); // 输出: Hello, my name is john_doe
访问对象的值

可以使用点操作符访问对象的属性:

typescript">const product = {
    name: "Laptop",
    price: 999.99
};

// 访问对象的值
console.log(`Product: ${product.name}`); // 输出: Product: Laptop
console.log(`Price: $${product.price}`); // 输出: Price: $999.99

TypeScript 类型模板

在 TypeScript 中,定义对象类型可以帮助确保结构的一致性。例如,创建一个包含详细信息的对象:

typescript">const book: { title: string; author: string; pages: number; summarize: () => void } = {
    title: "The Great Gatsby",
    author: "F. Scott Fitzgerald",
    pages: 218,
    summarize: function() {
        console.log(`${this.title} by ${this.author} has ${this.pages} pages.`);
    }
};

// 调用方法
book.summarize(); // 输出: The Great Gatsby by F. Scott Fitzgerald has 218 pages.

传递对象作为函数参数

可以将对象作为参数传递给函数,并在函数中使用类型定义来确保对象的结构正确。

示例
typescript">const car = {
    make: "Tesla",
    model: "Model S",
    year: 2021
};

const displayCarInfo = function(carInfo: { make: string; model: string; year: number }) {
    console.log(`Car Make: ${carInfo.make}`);
    console.log(`Car Model: ${carInfo.model}`);
    console.log(`Car Year: ${carInfo.year}`);
};

displayCarInfo(car);

// 输出:
// Car Make: Tesla
// Car Model: Model S
// Car Year: 2021

TypeScript 泛型详解

泛型(Generics)是一种强大的编程特性,允许在定义函数、类和接口时使用占位符表示类型,使得代码更加灵活和可重用。泛型能够处理多种数据类型,而不会丢失类型安全。

泛型的优势

  • 代码重用:可以编写与具体类型无关的通用代码,提高代码的复用性。
  • 类型安全:在编译阶段进行类型检查,避免运行时的类型错误。
  • 抽象性:支持编写更抽象和通用的代码,适应不同的数据类型和结构。

泛型标识符

在定义泛型时,常用的标识符有:

  • T:表示 “Type”,最常见的泛型类型参数。
  • K, V:通常用于表示键(Key)和值(Value)的泛型类型参数。
typescript">function echo<T>(arg: T): T {
    return arg;
}

泛型函数

使用泛型可以创建处理不同类型的函数。例如:

typescript">function wrapInArray<T>(item: T): T[] {
    return [item];
}

// 使用泛型函数
const numberArray = wrapInArray(123);
console.log(numberArray); // 输出: [123]

const stringArray = wrapInArray("Hello");
console.log(stringArray); // 输出: ["Hello"]

在这个例子中,wrapInArray 是一个泛型函数,接受一个参数并返回包含该参数的数组。

泛型接口

可以定义泛型接口,使其成员能够使用任意类型:

typescript">interface Pair<K, V> {
    key: K;
    value: V;
}

// 使用泛型接口
const numberStringPair: Pair<number, string> = { key: 1, value: "One" };
console.log(numberStringPair); // 输出: { key: 1, value: 'One' }

在此例中,定义了一个泛型接口 Pair,然后创建了一个包含数字和字符串的对象。

泛型类

泛型也可以应用于类的属性和方法:

typescript">class Container<T> {
    private items: T[] = [];

    addItem(item: T): void {
        this.items.push(item);
    }

    getItems(): T[] {
        return this.items;
    }
}

// 使用泛型类
const stringContainer = new Container<string>();
stringContainer.addItem("Hello");
console.log(stringContainer.getItems()); // 输出: ["Hello"]

在这个例子中,Container 是一个泛型类,能够存储任意类型的数组。

泛型约束

如果需要限制泛型的类型,可以使用泛型约束:

typescript">interface HasLength {
    length: number;
}

function logLength<T extends HasLength>(item: T): void {
    console.log(item.length);
}

// 正确使用
logLength("Hello"); // 输出: 5

// 错误使用,数字没有 length 属性
// logLength(123); // 编译错误

这里,logLength 函数接受一个参数,但有一个约束,要求传入的类型必须实现 HasLength 接口。

泛型与默认值

可以为泛型设置默认值,使得在不指定类型时使用默认类型:

typescript">function createPair<K = string, V = number>(key: K, value: V): Pair<K, V> {
    return { key, value };
}

// 使用带默认值的泛型函数
const defaultPair = createPair("Default");
console.log(defaultPair); // 输出: { key: 'Default', value: 0 }

const customPair = createPair<number, string>(1, "One");
console.log(customPair); // 输出: { key: 1, value: 'One' }

在此例中,createPair 函数具有默认类型参数。当未指定类型时,使用默认值。第一个调用使用了默认类型,而第二个调用则显式指定了类型。

泛型函数例子

下面是一个使用 TypeScript 编写的泛型排序方法,该方法可以对具有年龄属性的对象数组进行排序。示例中包括 AnimalPerson 两个接口,它们都有一个 age 属性。通过泛型函数,您可以轻松地对这些对象进行排序。

typescript">// 定义 Animal 接口,包含 age 属性
interface Animal {
    name: string;
    age: number; // 年龄属性
}

// 定义 Person 接口,包含 age 属性
interface Person {
    firstName: string;
    lastName: string;
    age: number; // 年龄属性
}

// 泛型排序函数,接收一个对象数组和一个比较函数
function sortByAge<T extends { age: number }>(arr: T[], ascending: boolean = true): T[] {
    // 使用 Array.sort 方法进行排序
    return arr.sort((a, b) => {
        // 比较年龄属性
        if (a.age < b.age) {
            return ascending ? -1 : 1; // 如果需要升序,则返回 -1,反之返回 1
        } else if (a.age > b.age) {
            return ascending ? 1 : -1; // 如果需要升序,则返回 1,反之返回 -1
        } else {
            return 0; // 年龄相等,返回 0
        }
    });
}

// 示例:创建 Animal 对象数组
const animals: Animal[] = [
    { name: "Dog", age: 5 },
    { name: "Cat", age: 3 },
    { name: "Elephant", age: 10 }
];

// 示例:创建 Person 对象数组
const persons: Person[] = [
    { firstName: "Alice", lastName: "Johnson", age: 30 },
    { firstName: "Bob", lastName: "Smith", age: 25 },
    { firstName: "Charlie", lastName: "Brown", age: 35 }
];

// 对动物按年龄升序排序
const sortedAnimals = sortByAge(animals);
console.log("Sorted Animals (Ascending):", sortedAnimals);

// 对人按年龄降序排序
const sortedPersons = sortByAge(persons, false);
console.log("Sorted Persons (Descending):", sortedPersons);
代码说明:
  1. 接口定义

    • AnimalPerson 接口分别定义了动物和人类对象的结构,包含一个 age 属性。
  2. 泛型排序函数

    • sortByAge 函数是一个泛型函数,接受一个对象数组 arr 和一个布尔值 ascending 作为参数,默认为升序。
    • 使用 Array.sort 方法对数组进行排序。
    • 比较对象的 age 属性,返回相应的排序值。
  3. 示例数据

    • 创建了一个动物数组 animals 和一个人类数组 persons
  4. 排序调用

    • 使用 sortByAge 函数对动物数组进行升序排序,并对人类数组进行降序排序。
输出示例:

运行该代码后,您将看到排序后的动物和人类对象数组的输出。

学习总结

本次学习了接口、类、对象和泛型四大概念。分别如下:
1、深入理解 TypeScript 接口的定义、联合类型、数组使用以及接口继承的特性。
2、TypeScript 类的定义、实例化、继承、方法重写以及接口实现等特性。
3、TypeScript 中对象的定义和使用,包括如何创建对象、访问其属性、添加方法以及将对象作为函数参数。
4、泛型是 TypeScript 中一个重要的特性,它使得编写可重用、灵活且类型安全的代码成为可能。通过使用泛型函数、接口和类,开发者可以有效地处理多种类型的数据,提高代码的清晰度和可维护性。
其中接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应是抽象的。其次由类实现接口的抽象方法。
可以包含以下几个模块(类的数据成员):

  • 字段 − 字段是类里面声明的变量。字段表示对象的有关数据。
  • 构造函数 − 类实例化时调用,可以为类的对象分配内存。
  • 方法 − 方法为对象要执行的操作。

对象是包含一组键值对的实例,其值可以是标量、函数、数组、对象等
泛型(Generics)是一种编程语言特性,允许在定义函数、类、接口等时使用占位符来表示类型,而不是具体的类型。
使用泛型的主要目的是为了处理不特定类型的数据,使得代码可以适用于多种数据类型而不失去类型检查。
泛型的优势包括:

  • 代码重用: 可以编写与特定类型无关的通用代码,提高代码的复用性。
  • 类型安全: 在编译时进行类型检查,避免在运行时出现类型错误。
  • 抽象性: 允许编写更抽象和通用的代码,适应不同的数据类型和数据结构。

http://www.niftyadmin.cn/n/5682717.html

相关文章

Stable Diffusion绘画 | Checkpoint Merger 模型融合

在我们的模型库中&#xff0c;经常会发现下载的模型&#xff0c;生成的图片颜色发灰&#xff0c;暗沉&#xff1a; 主要原因就是&#xff0c;我们下载的模型&#xff0c;作者训练时并没有加入VAE色调文件。 为了解决这个问题&#xff0c;我们可以使用 SD 自带额模型融合页面&am…

leetcode_55:跳跃游戏

给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输…

数据结构编程实践20讲(Python版)—03栈

本文目录 03 栈 StackS1 说明S2 示例基于列表的实现基于链表的实现 S3 问题&#xff1a;复杂嵌套结构的括号匹配问题求解思路Python3程序 S4 问题&#xff1a;基于栈的阶乘计算VS递归实现求解思路Python3程序 S5 问题&#xff1a;逆波兰表示法(后缀表达式)求值求解思路Python3程…

matlab入门学习(二)矩阵、字符串、基本语句、函数

一、矩阵 1、矩阵生成 %矩阵生成%直接法 A[1,2,3; 4,5,6; 7,8,9]%冒号一维矩阵&#xff1a;开始&#xff0c;步长&#xff0c;结束&#xff08;步长为1时可以省略&#xff09; B1:1:10 B1:10 %函数法%linspace(开始&#xff0c;结束&#xff0c;元素个数)&#xff0c;等差生成…

adb命令无反应或找不到设备处理方式记录

背景 最近更换电脑&#xff0c;android studio找不到设备&#xff1b;本文档对adb使用过程中遇到的文件进行记录&#xff0c;方便下次自己和其他同学遇到相同问题进行参考&#xff0c;如果不完善的地方请谅解&#xff0c;本文档仅包含个人遇到问题及解决方式。 问题 打开And…

K8S真正删除pod

假设k8s的某个命名空间如&#xff08;default&#xff09;有一个运行nginx 的pod&#xff0c;而这个pod是以kubectl run pod命令运行的 1.错误示范&#xff1a; kubectl delete pod nginx-2756690723-hllbp 结果显示这个pod 是删除了&#xff0c;但k8s很快自动创建新的pod,但是…

PMP--三模--解题--41-50

文章目录 14.敏捷--十二大原则--第1条--我们的最高目标是&#xff0c;通过尽早持续交付有价值的软件来满足客户的需求。--价值交付是敏捷原则的第一条。题目要“尽早交付”&#xff0c;不就是选C&#xff0c;快速交付吗&#xff0c;还是重点在于“跨职能团队”&#xff0c;选敏…

VMware下的ubuntu显示文字太小的自适应显示调整

我的情况 我使用的是4K的32寸显示器&#xff0c;分辨率为 3840 x 2160&#xff0c;ubuntu版本为18.04&#xff0c;默认的情况下系统分辨率为 3466 x 1842。 ​ 此时&#xff0c;显示的文字很小&#xff0c;虽然可以看清&#xff0c;但也比较吃力&#xff0c;在VMware窗口…