
TypeScript入门——3.类与对象
关于类与对象的介绍等可以直接参考:面向对象的程序设计基础
类的示例
以下是创建类与对象的简单示例:
class Person {
// 属性声明
name: string
age: number
// 构造器
constructor(name: string, age: number) {
this.name = name
this.age = age
}
// 方法
speak(): void {
console.log(`我叫: ${this.name}, 今年${this.age}岁`)
}
}
// Person实例
const p1 = new Person('zxb', 19)
p1.speak()
继承演示:
class Person {
// 属性声明
name: string
age: number
// 构造器
constructor(name: string, age: number) {
this.name = name
this.age = age
}
// 方法
speak(): void {
console.log(`我叫: ${this.name}, 今年${this.age}岁`)
}
}
class Student extends Person {
grade: string
// 构造器
constructor(name: string, age: number, grade: string) {
super(name, age);
this.grade = grade
}
// 重载speak方法
override speak() {
console.log(`我是学生, 我叫: ${this.name}, 今年${this.age}岁, 在读: ${this.grade}年级`)
}
study() {
console.log(`${this.name}正在努力学习中...`)
}
}
// Student实例
const stu = new Student('zxb', 19, '五百')
stu.speak()
stu.study()
属性修饰符
修饰符 | 含义 | 具体规则 |
---|---|---|
public | 公开的 | 可以被:类内部、子类、类外部访问 |
protected | 受保护的 | 可以被:类内部、子类访问 |
private | 私有的 | 可以被:类内部访问 |
readonly | 只读属性 | 属性无法修改 |
public修饰符:
class Person {
public name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
speak() {
console.log(`我叫: ${this.name}, 今年${this.age}岁`)
}
}
const p1 = new Person('张三', 18)
console.log(p1.name) // 类【外部】可以访问public的属性
子类同理
介绍一下构造器的简化版:
class Person {
constructor (
public name: string,
age: number
) { }
}
其他几个参考Java等语言即可
这里就演示readonly:
class Car {
constructor(
public readonly vin: string, // 车辆识别码,为只读
public readonly year: number, // 出厂年份, 为只读
public color: string,
public sound: string
) {
}
// 打印车辆信息
displayInfo() {
console.log(`
识别码: ${this.vin}
出厂年份: ${this.year}
颜色: ${this.color}
音响: ${this.sound}
`)
}
}
const car = new Car('1234567890', 2020, 'red', 'Benz')
car.displayInfo()
// car.vin = 'ajsdkfja;sldf' 无法修改
抽象类
概述:抽象类是一种无法实例化的类,专门用来定义类的结构和行为,类中可以写抽象方法,也可以写具体实现。抽象类主要用来为其派生类提供一个基础结构,要求其派生类必须实现其中的抽象方法。
通过以下场景,理解抽象类:
我们定义⼀个抽象类
Package
,表示所有包裹的基本结构,任何包裹都有重量属性weight
,包裹都需要计算运费。但不同类型的包裹(如:标准速度、特快专递)都有不同的运费计算⽅式,因此⽤于计算运费的calculate
⽅法是⼀个抽象⽅法,必须由具体的⼦类来实现
Package
类:
abstract class Package {
constructor(public weight: number) { }
// 抽象方法:运费计算
abstract calculate(): number
// 通用方法: 打印包裹详情
printPackage() {
console.log(`包裹重量为: ${this.weight}kg, 运费为: ${this.calculate()}元`)
}
}
StandardPackage
子类:
// 标准包裹
class StandardPackage extends Package {
constructor(
weight: number,
public uniPrice: number // 每公斤固定费率
) { super(weight) }
calculate(): number {
return this.weight * this.uniPrice
}
}
ExpressPackage
子类:
// 特快包裹
class ExpressPackage extends Package {
constructor(
weight: number,
private uniPrice: number,
private additional: number // 超出10kg后的附加费
) {
super(weight);
}
calculate(): number {
if (this.weight > 10) return 10 * this.uniPrice + (this.weight - 10) * this.additional
return this.weight * this.uniPrice
}
}
接口(interface)
interface
是⼀种定义结构的⽅式,主要作⽤是为:类、对象、函数等规定**⼀种契约**,这样可以确保代码的⼀致性和类型安全,但要注意interface
只能定义格式,不能包含任何实现 !
定义类结构:
interface PersonInterface {
name: string
age: number
speak(n: number): void
}
// 定义一个类 Person, 实现 PersonInterface 接口
class Person implements PersonInterface {
constructor(
public name: string,
public age: number
) {
}
speak(n: number): void {
for (let i = 0; i < n; i++) {
console.log(`My name is ${this.name}, I am ${this.age} years old, this are ${i} times`);
}
}
}
const p1 = new Person('Tom', 18);
p1.speak(5)
定义对象结构:
interface UserInterface {
name: string
readonly gender: string
run: (n: number) => void
}
const user: UserInterface = {
name: "张三",
gender: "男",
run(n) {
console.log(`奔跑了${n}米`)
}
}
定义函数结构:
interface CountInterface {
(a: number, b: number): number;
}
const cout: CountInterface = (x, y) => {
return x + y;
}
接口之间的继承
接口也能进行继承:
interface PersonInterface {
name: string // 姓名
age: number // 年龄
}
interface StudentInterface extends PersonInterface {
grade: string // 年级
}
const stu: StudentInterface = {
name: "张三",
age: 25,
grade: "高三"
}
泛型
关于泛型:11.(new)泛型
泛型就如同字面意思,可以是任何一个未指定的类型,为什么是未指定呢?
因为一旦指定后,泛型就会变成指定的具体类型,那么它的作用就是为了让一个函数等的参数或返回值提供更多的可能性。
比如:一个接受网络请求的类 Result
那么它就可以接收任意的一个类型,如字符串、数字、json等...
语法:
泛型函数
:
function logData<T>(data: T): T {
console.log(data)
return data
}
logData<number>(100)
logData<string>('hello')
泛型可以有多个
:
function logData<T, U>(data1: T, data2: U): T | U {
console.log(data1,data2)
return Date.now() % 2 ? data1 : data2
}
logData<number, string>(100, 'hello')
logData<string, boolean>('ok', false)
泛型接口
:
interface PersonInterface<T> {
name: string,
age: number,
extraInfo: T
}
let p1: PersonInterface<string>
let p2: PersonInterface<number>
p1 = { name: '张三', age: 18, extraInfo: '⼀个好⼈' }
p2 = { name: '李四', age: 18, extraInfo: 250 }
泛型约束
:
interface LengthInterface {
length: number
}
// 约束规则是:传⼊的类型T必须具有 length 属性
function logPerson<T extends LengthInterface>(data: T): void {
console.log(data.length)
}
logPerson<string>('hello')
// 报错:因为number不具备length属性
// logPerson<number>(100)
泛型类
:
class Person<T> {
constructor(
public name: string,
public age: number,
public extraInfo: T
) { }
speak() {
console.log(`我叫${this.name}今年${this.age}岁了`)
console.log(this.extraInfo)
}
}
// 测试代码1
const p1 = new Person<number>("tom", 30, 250);
// 测试代码2
type JobInfo = {0
title: string;
company: string;
}
const p2 = new Person<JobInfo>("tom", 30, { title: '研发总监', company: '发发发科技公司' });
类型声明文件
类型声明文件是TS的一种特殊文件,通常以
.d.ts
作为扩展名。它的主要作用是位现有的JavaScript提供类型信息,似的TS能够在使用这些JS库或模块时,进行类型检查和提示。
js如下:
export function add(a, b) {
return a + b;
}
export function mul(a, b) {
return a * b;
}
d.ts
如下:
declare function add(a: number, b: number): number;
declare function mul(a: number, b: number): number;
export { add, mul };
最后在ts文件中就可以引用js文件,并且也可以进行类型检查了
// example.ts
import { add, mul } from "./demo.js";
const x = add(2, 3); // x 类型为 number
const y = mul(4, 5); // y 类型为 number
console.log(x,y)
- 感谢你赐予我前进的力量