TypeScript学习笔记(9)-类

什么是类?

类是对一个对象的描述,可以使理解更具象化。

比如:传统汽车BBA,电动汽车 目前比较火的问界M9 。
电动汽车也继成了汽车的基本属性对吧。比如有几个车轮,几个车门,车的颜色,车的品牌。我们买车都是看品牌对吧 。
它也继成了车的行为比如,可以加速,刹车,拐弯。

 当 电动汽车继成 汽车时,它包括了汽车的所有属性和方法,以及扩展了一个 属性imax 巨幕电影 和方法 看电影 

类组件

  • 属性(也称为字段)是对象的数据(或特性)。 这些是可以在代码中设置或返回的对象的定义特征。
  • constructor 是一个特殊函数,用于基于类创建和初始化对象。 创建类的新实例时,构造函数使用类形状创建一个新对象,并使用传递给它的值对其进行初始化。
     
  • 访问器是一种用于 get 或 set 属性值的函数类型。 属性可以是只读的,只需省略类中的 set 访问器,或者通过省略 get 访问器使其不可访问(如果尝试访问它,该属性将返回 undefined,即使在初始化期间为其赋值也是如此。)
     
  • 方法是定义对象可以执行的行为或操作的函数。 可以调用这些方法来调用对象的行为。 还可以定义只能从类本身访问的方法,并且通常由类中的其他方法调用以执行任务。

设计说明

可以创建类来为数据建模、封装功能、提供模板以及许多其他用途。 因此,上面列出的组件在你创建的每个类中都不是必需的。 可能只需要实用工具对象的方法和构造函数,或者只需要属性来管理数据。

访问器通常仅在需要控制对值的访问(如实现验证)或动态计算值时使用。 如果你的类严格存储值并且不需要访问器提供的其他功能,则可以使用属性。

 具体示例:

创建类:

1.语法  使用 class 关键字后跟类名 name ,按照约定,类名为 PascalCase。

class Car {
    // Properties 属性 
   
    // Constructor  构造器

    // Accessors 访问器

    // Methods    方法
}
声明属性

可以将类属性视为在初始化时传递给对象的原始数据。

代表一类通用的特征。

语法: 属性名:类型

    // Properties 属性  一般属性是适用于任何汽车的属性 (一类通用的特征)
    _make: make; // 品牌 私有属性 (以一个下划线开头)
    _color: string; // 颜色 
    _doors: string; // 车门数

属性名称前的下划线 (_) 在属性声明中不是必需的。

但它提供了一种方法来区分属性声明和可通过构造函数访问的参数,

同时仍以直观方式将两者结合在一起。

定义类构造函数

实例化类的分类 

  • 实例类型
  • 静态化类型

constructor 函数初始化类的属性:

  • constructor 关键字。
  • 参数列表,定义在创建新实例时将传递给新对象的参数。 在定义参数列表时,请记住:
  1. 不需要为类中的每个属性定义参数。
  2. 与所有 TypeScript 函数一样,参数可以是必需的或可选的,可以是默认值,也可以是其他参数。 (这是与 JavaScript 的一个关键区别。)
  3. 参数名称可以与属性名称不同。 请记住,当你使用此类型的对象时,这些名称将出现在 Intellisense 中,因此请使用具有足够说明性的名称。
  • 属性赋值。 每个语句都将参数的值赋给属性的值。 要表明你正在访问类的成员(本例中为属性),请应用 this. 关键字。

一个类最多只能包含一个 constructor 声明。 如果类不包含 constructor 声明,则提供自动构造函数。

    // 定义类构造函数
    // Constructor  构造器
    constructor(make: string, color: string, doors = 4) {
        this._make = make;
        this._color = color;
        this._doors = doors;
    }
定义访问器

虽然你可以直接访问类属性(它们在默认情况下都是 public),但 TypeScript 支持使用 getter/setter 作为拦截对属性的访问的方法。
这使你可以更精细地控制如何在每个对象上访问成员。比如 使用 get 和 set 块来

  1. 验证数据
  2. 施加约束
  3. 在将数据返回到程序之前对数据执行其他操作
    // Accessors 访问器
    //定义属性 _make get
    get make() {
        return this._make;
    }
    //定义属性 _make set
    set make(makeVal) {
        this._make = makeVal
    }

    // 格式化输出内容
    get color() {
        return '车的颜色是 ' + this._color;
    }
    set color(color) {
        this._color = color;
    }

    get doors() {
        return this._doors;
    }
    // 额外逻辑处理或数据校验
    set doors(doors) {
        if ((doors % 2) === 0) {
            this._doors = doors;
        } else {
            throw new Error('门必须是偶数');
        }
    }
定义类方法

在类中定义的函数即称为方法,描述类的可执行行为。

类中的方法没有function 关键字,因为一是不允许二是保持了语法简洁。

   // Methods  方法  缺省function关键字,保持语法简洁
    //加速
    accelerate(speed: number): string {
        return `${this.worker()} 加速到 ${speed} Km/h.`
    }
    //制动刹车
    brake(): string {
        return `${this.worker()} 刹车了.`
    }
    //转向拐弯
    turn(direction: 'left' | 'right'): string {
        return `${this.worker()} 向 ${direction} 拐弯了`;
    }
实例化类

基于上面的操作 我们已经创建好了Car类。

  1. 该类有三个属性。
  2. 可以获取和设置这些属性的值。
  3. 具有四种方法。

具体怎么使用呢

let Car1 = new Car('奔驰', 'Black', 4);  // 实例化对象 所有参数都传入
console.log(Car1._color);  // 输出 Black
console.log(Car1.color);  // 输出 车的颜色是 Black

let Car2 = new Car('奔驰2号', 'red', 3); //编译和运行并不报错  构造函数只是赋值给了_dorrs属性 验证是在访问器 doors set 里面
// Car2.doors = 5;  // 抛出错误 门必须是偶数

let Car3 = new Car('奔驰3号', 'blue',);
console.log(Car3.doors); //门未赋值 则输出默认值4

//方法调用
console.log(Car1.accelerate(40)); //输出 奔驰 加速到 40 Km/h.
console.log(Car1.brake());//输出 奔驰 刹车了.
console.log(Car1.turn('left'));//输出 奔驰 向 left 拐弯了
访问修饰符

默认情况下 ,所有类成员均为 public,即可以运行外部访问

访问修饰符说明
public如果不指定访问修饰符,则默认为 public。
还可以使用 public 关键字显式地将成员设置为 public。
private如果使用 private 关键字修改成员,则不能从其包含类的外部访问该成员。
protectedprotected 修饰符的作用与 private 修饰符非常类似,但也可以在派生类中访问声明 protected 的成员。 (后面会介绍)

此外,还可以通过使用 readonly 修饰符将属性设置为 readonly。 readonly 属性只能在其声明时或在 constructor 中初始化时设置。

class Car {
    // 声明类属性 可以将类属性视为在初始化时传递给对象的原始数据
    // Properties 属性  一般属性是适用于任何汽车的属性 (一类通用的特征)
    private _make: string; // 品牌 私有属性 (以一个下划线开头)
    private _color: string; // 颜色 
    private _doors: number; // 车门数


....
....

    //私有方法,外部不可访问
    private worker(): string {
        return this._make;
    }

}

直接访问会编辑器会提示异常

 定义静态属性

实例属性与静态属性

以上定义的类的属性和方法都是实例属性,可以通过实例化(New 类名)调用。而静态属性和方法由类的所有实例共享

注意 定义语法区别,调用区别

语法  在属性或方法名称前使用 static 关键字 

class Car {
    //静态属性 类实例化次数
    private static numberOfCars: number = 0;
    
    ...

    // 定义类构造函数
    // Constructor  构造器
    constructor(make: string, color: string, doors = 4) {
        ...
        //每实例一次加1
        Car.numberOfCars++;
    }


...
...

    //定义静态方法
    public static getNumberOfCars(): string {
        return "类被实例化了:" + Car.numberOfCars;
    }

}

// 实例化3次后
...

//类直接调用静态方法
console.log(Car.getNumberOfCars()); //输出  类被实例化了:3
继承与扩展类

关系描述 : 基类与派生类 或者叫 父类与子类

通过继成与扩展可以在不影响类本身功能的情况下额外扩展类的功能。以便满足不同需求

  • 代码可重用性。 可以一次性开发,并在许多地方重用。 此外,这有助于避免在代码中出现冗余。
  • 可以使用一个基类派生任意数量的子类。
  • 不必在许多具有类似功能的不同类中更改代码,只需在基类中更改一次即可。
子类 constructor 
  1. 参数列表可以包含基类和子类的任何属性。 
  2. 在 constructor 正文中,你必须添加 super() 关键字以包括来自基类的参数。 super 关键字在运行时执行基类的 constructor
  3. 在引用子类中的属性时,super 关键字必须出现在对 this. 的任何引用之前。
重写方法

基类的方法不满足情况 则 派生类可以重新父类的方法

 比如 电动汽车有APE自动刹车系统 重新刹车方法


//电动汽车 问界9
class ElectricCar extends Car {
    // 巨幕电影
    private _imax: boolean;

    // Constructor
    constructor(make: string, color: string, imax: boolean, doors = 2) {
        super(make, color, doors);
        this._imax = imax;
    }

    get imax() {
        return this._imax;
    }

    set imax(imax) {
        this._imax = imax;
    }

    //重写 brake
    brake(): string {
        return `${this.worker()} 电动车 APE 自动刹车了. 救了一命`
    }

    watch() {
        console.log(this.worker() + " 看巨幕电影。")
    }
}

let wenjie9 = new ElectricCar('问界9', 'gray', true, 2);
wenjie9.watch();                  // 输出 问界9 看巨幕电影。
console.log(wenjie9.brake());     // 输出 问界9 电动车 APE 自动刹车了. 救了一命

父类的组件 修饰符 改成 protected 子类才可以访问

子类的方法重写 必须和父类一样 参数和返回类型一样,具体实现细节可以不

配合接口使用

接口可用来建立描述对象的必需属性及其类型的“代码协定”。

使用 implements 实现一个或多个接口。

  1. 类实现接口
  2. 接口继承接口
  3. 接口继承类 作为一个类型使用
inerface A {

}

inerface B {

}

//实现多个接口
class Car implements A, B{

}

//接口继接口
interface C extends A {

}

class D{

}


//接口继成类
interface F extends D {

}

汽车属于一种交通工具 ,实现一个交通工具接口,可以定义一个标准的实现。
 

何时使用接口?

  1. 接口是一种 TypeScript 设计时构造。
  2. 由于 JavaScript 没有接口概念,因此当 TypeScript 转译为 JavaScript 时,它们就会被删除。这意味着它们完全是无足轻重的,没有在生成的文件中占用空间,对将要执行的代码不会产生负面影响。
  3. TypeScript 允许使用接口来定义数据结构,而无需类。 可以定义参数对象,定义接口结构对象。等

 关于接口,TypeScript 的一个关键特性是不需要类。 这允许你在需要定义数据结构的时候使用它们,而无需创建完整的类实现。

何时使用类?

类允许你定义实现的详细信息。 接口仅定义数据的结构。
类允许你定义方法、字段和属性。 类还提供了模板化对象的方法,进而定义默认值。

知识检查

类定义中可包含多少 constructor 函数?

       1个(可以在类定义中声明一个 constructor 函数。 如果省略,将为你提供自动构造函数。)

如果省略类属性的 get 访问器,会发生什么?

         你将无法从代码中返回其值。(如果省略 get 访问器,属性将不可访问。)

如果你不希望从类外部的代码中访问方法,但又想要使其在派生自类的其他类中可用,应使用哪种访问修饰符?

         protected( protected 修饰符可防止方法在类的外部可见,同时允许派生类使用它。)

扩展类时,super 关键字的用途是什么?

 它在运行时执行基类 constructor。(在初始化子类中的属性之前,super 关键字执行基类 constructor。 它必须出现在任何 this. 实例之前。)

  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值