【TypeScript】类、类的属性及抽象类(七)

news2024/12/29 10:32:38

【TypeScript】类、类的属性及抽象类(七)


在这里插入图片描述

    • 【TypeScript】类、类的属性及抽象类(七)
        • 一、前言
        • 二、语法及属性定义
        • 三、类的继承
        • 四、属性类型
        • 五、readonly修饰符
        • 六、static 静态属性
        • 七、存取器-get/set
        • 八、抽象类

一、前言

传统的JavaScript程序使用基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员来讲就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的。

从ECMAScript 2015,也就是ECMAScript 6开始,JavaScript程序员将能够使用基于类的面向对象的方式。

使用TypeScript,允许开发者可以使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,而不需要等到下个JavaScript版本。

二、语法及属性定义

语法:

class class_name { 
    // 类作用域
}

形如上述语法,通过关键字 class定义类。
Typescript类也和其他静态语言类似,其中包含 字段、构造函数、方法

我们举一反三,利用刚才学到的知识进行定义一个学生Student 类,类中包含一个 name 属性,同时能够获取到学生的姓名 getName 方法,启动机智如你的大脑,看看该如何定义这个类:


class Student {
  name: string,
  constructor(name: string) {
    this.name = name;
  }
  getName(){
    return 'my name is ' + this.name;
  }
}

我们声明了Student 类,这个Student类有3个成员:一个叫做 name 的属性,一个constructor构造函数和一个 getName 方法。

编译后内容会是下面这样子:

"use strict";
var Student = /** @class */ (function () {
    function Student(name) {
        this.name = name;
    }
    Student.prototype.getName = function () {
        return 'my name is ' + this.name;
    };
    return Student;
}());

我们将这个Student 实例化,看看具体使用


const student: Student = new Student('suwu150');
console.log(student.getName())

在这里插入图片描述

三、类的继承

前面阶段,我们其实已经使用过类的继承和接口的继承,但只是用做例子展示,这里我们深入了解下具体的实现。

在TypeScript里,我们可以使用常用的面向对象模式。 基于类的程序设计中一种最基本的模式是允许使用继承来扩展现有的类。

语法:class ClassA extends ClassB {}

形如上述,ClassA 的定义是基于继承 ClassB 的方案实现的。

定义一个 Person类,让 Student 继承。


class Person {
  getName(){
    return 'person say hi...: ';
  }
}

class Student extends Person  {
  getStudentName(){
    return 'student say hi...: my name is ';
  }
}

const student: Student = new Student();

console.log(student.getName())
console.log(student.getStudentName())

Student类 是从 基类Person 中继承了 属性方法。 这里 Student 是一个 派生类,它派生自 Person 基类,通过 extends 关键字实现继承与派生。
派生类通常被称作 子类,基类通常被称作 超类

由于继承关系,student实例也就能够调用基类的 getName 方法,也能够调用自己的 getStudentName方法

我们将这段代码进行TS编译,可以看看编译后的结果。

在这里插入图片描述
可以看到继承的实现的底层原理。

我们再来给类添加几个属性看看该如何定义,如何在方法中使用这些属性。

class Person {
  name: string;
  constructor(name: string) { this.name = name; }
  getName(){
    return 'person say hi...: ' + this.name;
  }
}
class Student extends Person  {
  constructor(name: string) { super(name); }
  getName(){
    return super.getName();
  }
}
class Teacher extends Person  {
  constructor(name: string) { super(name); }
  getName(){
     return super.getName();
  }
}

const student: Student = new Student('Student');
const teacher: Teacher = new Teacher('Teacher');
console.log(student.getName())
console.log(teacher.getName())


这个例子中,我们使用 extends 关键字创建了 Person 的两个子类,分别是 Student 和 Teacher。
派生类包含了一个 构造函数,它 必须调用 super(),它会执行基类的构造函数在构造函数里访问 this的属性之前, 一定要调用 super()。 这条规则和其他静态语言类似,是TypeScript强制执行的一条重要规则,也只有这样才能去初始化父类的一些属性。

这里我们在子类里边重写了父类的方法getName,重写父类方法方法名需要和父类保持一致。

四、属性类型

与Java静态语言类似,类里边的属性也是区分公共,私有与受保护三种类型,分别用 public、private、protected 表示。
需要注意的是,为什么我们之前没有考虑过这些类型,但我们能够随意调用?

那就是在TypeScript里,成员都默认为 public

下面我们来看看显示定义的一些操作:

class Person {
    public name: string;  // name属性标识为public
    private age: number; // age标识为private
    protected score: string;  // 不能在 Person类外使用 name,但仍然可以通过 子类的实例方法访问,因为 子类是由 Person派生而来的
    public constructor(theName: string) { this.name = theName; }
    public move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

我们将以上类进行实例化使用

class Person {
    public name: string;  // name属性标识为public
    private age: number; // age标识为private
    protected score: string;  // 不能在 Person类外使用 name,但仍然可以通过 子类的实例方法访问,因为 子类是由 Person派生而来的
    public constructor(theName: string, age: number, score: string) {
        this.name = theName;
        this.age = age;
        this.score = score;
    }
    public move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}
class Student extends Person {
    move() {
        super.move(200);
        console.log(this.score) // 调用父级的protected
    }
}
const student = new Student('suwu150', 20, '2323')
student.move();
console.log(student.name) // public可以直接访问
console.log(student.age) // private不可以直接访问,报错
console.log(student.score) // protected不可以直接访问,报错,但能够被子类Student访问

请添加图片描述

五、readonly修饰符

我们在设置类中的变量或者属性的时候,有时我们期望外界用户不能够修改,此时我们就可以使用readonly这个属性来实现。

可以使用 readonly关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。

class Person {
    readonly name: string;
    readonly numberOfLegs: number = 2;
    constructor (theName: string) {
        this.name = theName;
    }
}
let person = new Person("suwu150");
person.name = "suwu150 suwu150"; // 错误! name 是只读的.

在这里插入图片描述

六、static 静态属性

我们也能够定义类的静态成员,可以用 static 关键字 定义静态属性,这些属性是属于类本身而非类的实例的属性。静态属性可以用来存储类级别的数据,例如单例模式中的实例对象,也可以用来提供类级别的函数和常量。

class MyClass {
  static count = 0;

  static incrementCount() {
    this.count++;
  }
}

console.log(MyClass.count); // 0
MyClass.incrementCount();
console.log(MyClass.count); // 1

在上面的例子中,我们定义了一个静态属性 count 和一个静态函数 incrementCount。我们可以直接通过类名来访问这些静态属性和函数,而不需要创建类的实例。

七、存取器-get/set

TypeScript支持通过 getters/setters 来截取对对象成员的访问。 它能帮助你有效的控制对象成员的访问。

  • Getter的形式是在属性方法前增加get,用于返回对象的属性值。
  • Setter的形式是在属性方法前增加set,用于设置对象的属性值。

它们可以像普通属性一样使用,只不过在具体获取值或者设置值的时候,进行监听中间处理。以下是一个示例:

class Person {
  private _name: string;

  get name(): string {
    return this._name;
  }

  set name(value: string) {
    this._name = value;
  }
}

let person = new Person();
person.name = "John";
console.log(person.name); // 输出 "John"

在上面的示例中,我们定义了一个 Person类,并在该类中定义了一个名为 _name 的私有属性。然后我们使用 getterssetters 方法来访问该属性。在类外部,我们可以像普通属性一样来设置和获取属性值。当我们设置值的时候,会调用set name(value: string)方法,当我们获取值的时候,会调用get name(): string 方法。注意,在setter方法中,我们使用了value参数来设置属性值。

八、抽象类

抽象类可以做为其它派生类的基类使用。 它们不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。

抽象类可以包含 抽象方法非抽象方法
抽象方法没有具体的实现,只有方法签名,必须在子类中实现。而非抽象方法则可以有具体的实现,子类可以直接继承或者重写.

语法: abstract class ClassNameA { }

其中,ClassNameA就是一个抽象类

abstract class Person {
  abstract sayHi(): void; // 抽象方法
  eat(): void { // 非抽象方法
    console.log("eat food...");
  }
}

上面就是定义了一个抽象类,我们在子类中进行实现。

class Student extends Person {
  sayHi(): void {
    console.log("hi...");
  }
  singsong(): void {
    console.log("singsong...");
  }
}
let person: Person = new Person(); // 错误:不能创建一个抽象类的实例
let student: Person = new Student(); //允许对一个抽象子类进行实例化和赋值
student.sayHi(); // 输出 "hi..."
student.eat(); // 输出 "eat food..."
student.singsong(); // 错误:"Property 'singsong' does not exist on type 'Person'."

需要注意的是,如果子类继承了一个抽象类,则必须实现其所有的抽象方法,否则子类本身也必须声明为抽象类。

在这里插入图片描述

以上就是TypeScript中类的一些常规用法。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1033920.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

定制SQLmap和WAF绕过

1. SQLmap tamper 脚本编写 以sqli-lab第26关为例 输入?id1’ --,报错字符型注入 考虑闭合问题,输入?id1’ and 1,但是回显中and和空格消失了,可知and和空格被过滤了 因为and和or被过滤考虑使用双写绕过手段,空格使…

2023华为杯数学建模D题第三问——区域双碳目标情景设计样例

在第二问建立好预测模型的基础上,如何设计第三问所说的区域双碳路径,以对宏观政策进行指导! 采用STIRPA的基本模型对中国碳达峰时间进行预测,对该模型公式两边取对数得到: 其中:P为人口,A为GDP…

NIO圣经:一次穿透NIO、Selector、Epoll底层原理

此pdf电子书,是尼恩架构团队持续升级、持续迭代的作品。 目标是,通过不断升级、持续迭代,为大家构筑一个超底层、超强悍的高性能技术内功。 原 :《九阳真经:彻底明白操作系统 select、epoll 核心原理》 改&#xff1…

2023年研赛华为杯选题人数发布

选题人数发布!经过长达30个小时,各个平台的相关选题投票、相关文章阅读量等各项数据进行统计,利用之前的评估办法(详见注释)。在开赛后30小时,我们基本确定各个赛题选题人数,大致为 题号选题人数…

时间轮算法

思考 假如现在有个任务需要3s后执行,你会如何实现? 线程实现:让线程休眠3s 如果存在大量任务时,每个任务都需要一个单独的线程,那这个方案的消耗是极其巨大的,那么如何实现高效的调度呢? 时…

兰贡生物:打造生物医药研发“独角兽”

当我们站在医学科学的最前沿,探索着无尽的健康奥秘时,生物制药行业正经历着前所未有的变革和机遇。新的疾病不断涌现,现有的治疗方法也在不断演进,这需要有着创新精神和科学追求的企业来推动新药研发的进程。值此时代背景下&#…

网络安全—黑客技术—自学笔记

目录梗概 一、自学网络安全学习的误区和陷阱 二、学习网络安全的一些前期准备 三、网络安全学习路线 四、学习资料的推荐 想自学网络安全(黑客技术)首先你得了解什么是网络安全!什么是黑客! 网络安全可以基于攻击和防御视角来…

Linux常用命令—find命令大全

文章目录 一、find命令常用功能1、find命令的基本信息如下。2、按照文件名搜索3、按照文件大小搜索4、按照修改时间搜索5、按照权限搜索举例:6、按照所有者和所属组搜索7、按照文件类型搜索8、逻辑运算符 一、find命令常用功能 1、find命令的基本信息如下。 命令名…

力扣213打家劫舍2(简单动态规划)

题目描述: 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如…

1790_给通过USB连接到树莓派的NTFS硬盘设置固定的挂载名称

全部学习汇总: GreyZhang/little_bits_of_raspberry_pi: my hacking trip about raspberry pi. (github.com) 我用过好几个树莓派形式的单板电脑,但是遇到过磁盘挂载位置不确定的时候。有些甚至不会自动挂载。这些行为跟对应的OS的行为是相关的&#xff…

Mallox勒索病毒:最新变种.mallox_lab袭击了您的计算机?

引言 在数字化时代,数据是我们生活和工作的重要组成部分,但同时也引发了各种网络威胁,.mallox_lab勒索病毒便是其中之一。这种恶意软件以其加密文件并勒索赎金的方式而闻名,给个人和组织带来了巨大的风险和损失。本文将深入探讨.…

【小沐学C++】C++ MFC中嵌入64位ActiveX控件(VS2017)

文章目录 1、简介1.1 MFC1.2 ActiveX 2、VS2017添加ActiveX控件结语 1、简介 1.1 MFC Microsoft 基础类 (MFC) 库针对大部分 Win32 和 COM API 提供面向对象的包装器。 虽然此包装器可用于创建极为简单的桌面应用程序,但当你需要开发具有多个控件的更复杂的用户界…

你真的懂ArrayList吗?

ArrayList底层原理 ​ 1.ArrayList动态扩容的方法? 使用空参创建集合,在底层创建一个长度默认为0的数组;添加第一个元素时,底层会创建一个数组长度为10的数组;存满的时候,数组会自动扩容1.5倍;…

【算法思想-排序】按出现频率排序 - 力扣 1636

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

基于STM32+华为云IOT设计的智能车库管理系统

一、项目介绍 随着城市化进程和汽车拥有率的不断提高,停车难的问题也日益凸显。在城市中,停车场是一个非常重要的基础设施,但是传统的停车场管理方式存在很多问题,比如车位难以管理、停车费用不透明等。为了解决这些问题&#xf…

基于Vue+ELement搭建登陆注册页面实现后端交互

🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《ELement》。🎯🎯 &#x1…

C语言入门Day_24 函数与指针

目录 前言: 1.指针和数组 2.函数和指针 3.易错点 4.思维导图 前言: 我们知道数组是用来存储多个数据的,以及我们可以用指针来指向一个变量。那么我们可以用指针来指向一个数组中的数据么? 指针除了可以像指向一个变量一样指…

【C++心愿便利店】No.6---C++之拷贝构造函数

文章目录 一、拷贝构造函数的引入二、拷贝构造函数 👧个人主页:小沈YO. 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 📋专栏:C 心愿便利店 🔑本章内容:拷贝构造函数 记得 评…

python安全工具开发笔记(四)——python网络编程

一、C/S架构 什么是C/S架构 C : Client S : Server。客户机和服务器结构。 Server 唯一的目的就是等待Client 的请求,Client 连上 Server 发送必要的数据,然后等待Server端完成请求的反馈。 C/S网络编程 Server端进行设置,首先创建一个通信…

怎么选择AI伪原创工具-AI伪原创工具有哪些

在数字时代,创作和发布内容已经成为了一种不可或缺的活动。不论您是个人博主、企业家还是网站管理员,都会面临一个共同的挑战:如何在互联网上脱颖而出,吸引更多的读者和访客。而正是在这个背景下,AI伪原创工具逐渐崭露…