【TypeScript】ts中的Classes使用方法介绍

简言

TypeScript 完全支持 ES2015 中引入的类关键字。
与 JavaScript 语言的其他功能一样,TypeScript 添加了类型注解和其他语法,允许您表达类与其他类型之间的关系。
class类是一个较重要的知识。

Classes

类声明

ts中类的声明和js中的高度相似。
类定义:以class关键字声明,后面加类名(大驼峰),之后是花括号包裹类体,constructor构造函数可以不定义。

class Point {x = 0y = 0
}const pt = new Point()
console.log(pt.x,pt.y);class Point2 {x : numbery : numberconstructor(x: number, y: number) {this.x = xthis.y = y}
}
const pt2 = new Point2(1,1)
console.log(pt2.x,pt2.y);

就像使用 const、let 和 var 一样,类属性的初始化器将用于推断其类型,或者显示定义类型。

类属性

类属性和其他变量定义类型一样,默认可见性是public(公共的)。
若是想只读,前面需要加 readonly修饰,这样在构造函数之外无法赋值。

class Greeter {readonly name: string = "world";name2 = 'zsk'constructor(otherName?: string) {if (otherName !== undefined) {this.name = otherName;}}
}

类方法

类的函数属性称为方法。方法可以使用与函数和构造函数相同的类型注解,默认可见性是public(公共的)。
除了标准的类型注解,TypeScript 没有为方法添加任何新内容。

class Point {x = 10;y = 10;scale(n: number): void {this.x *= n;this.y *= n;}
}

类中的方法前面可以加set和get修饰。
TypeScript 对访问器有一些特殊的推理规则:

  • 如果存在 get 但没有 set,则属性自动为只读属性。
  • 如果未指定设置器(setters)参数的类型,则根据获取器(getters)的返回类型进行推断。
  • 获取器和设置器必须具有相同的成员可见性。
class Thing {_size = 0;get size(): number {return this._size;}set size(value: string | number | boolean) {let num = Number(value);// Don't allow NaN, Infinity, etcif (!Number.isFinite(num)) {this._size = 0;return;}this._size = num;}
}

实现和继承

与其他具有面向对象特性的语言一样,JavaScript 中的类可以从基类继承。

实现 implements

您可以使用 implements 子句来检查类是否满足特定接口。如果类未能正确实现该接口,则会出错:

interface Pingable {ping(): void;
}class Sonar implements Pingable {ping() {console.log("ping!");}
}
//errors
class Ball implements Pingable {pong() {console.log("pong!");}
}

类也可以实现多个接口,例如类 C 实现 A、B {。

另外,implements 子句只是检查类是否可以被视为接口类型。它根本不会改变类或其方法的类型。

interface Checkable {check(name: string): boolean;
}class NameChecker implements Checkable {check(s) {// Notice no error herereturn s.toLowerCase() === "ok";}
}

继承 extends

类可以从基类扩展而来。派生类拥有基类的所有属性和方法,还可以定义其他成员。

class Animal {move() {console.log("Moving along!");}
}class Dog extends Animal {woof(times: number) {for (let i = 0; i < times; i++) {console.log("woof!");}}
}const d = new Dog();
// Base class method
d.move();
// Derived class method
d.woof(3);

派生类也可以覆盖基类的字段或属性。您可以使用 super. 语法访问基类方法。
TypeScript 强制规定派生类始终是其基类的子类型。
例如,下面是重写方法的合法方式:

class Base {greet() {console.log("Hello, world!");}
}class Derived extends Base {greet(name?: string) {if (name === undefined) {super.greet();} else {console.log(`Hello, ${name.toUpperCase()}`);}}
}const d = new Derived();
d.greet();
d.greet("reader");// Alias the derived instance through a base class reference
const b: Base = d;
// No problem
b.greet();

派生类必须遵守符合(覆盖)基类的的类型。

执行顺序:

  • 基类字段初始化
  • 基类构造函数运行
  • 派生类字段初始化
  • 运行派生类构造函数

类成员可见性

类属性和类函数都是类成员。
您可以使用 TypeScript 来控制某些方法或属性是否对类外的代码可见。
可见性分为以下三种:

  • public —— 类成员的默认可见性为 public。公共成员可以在任何地方被访问,由于 public 已是默认的可见性修饰符,因此您无需在类成员上写入该修饰符,但出于样式/可读性的考虑,您可能会选择这样做。
  • protected —— 受保护成员只对其所声明类的子类可见。
  • private —— 私有的,只能自己访问。private 和 protected 类似,但不允许子类访问该成员。

与 TypeScript 类型系统的其他方面一样,private 和 protected 仅在类型检查过程中执行。这意味着,JavaScript 运行时构造(如 in 或简单的属性查询)仍可访问私有或受保护成员。

private 还允许在类型检查时使用括号符号进行访问。这使得单元测试等工作更容易访问声明为私有的字段,但缺点是这些字段是软私有的,不能严格执行隐私保护(这个感觉是弊端,最好不要这样做)。

class MySafe {private secretKey = 12345;
}const s = new MySafe();
// OK
console.log(s["secretKey"]);

静态成员

类可能有静态成员。这些成员与类的特定实例无关。可以通过类构造函数对象本身访问它们。

class MyClass {static x = 0;static printX() {console.log(MyClass.x);}
}
console.log(MyClass.x);
MyClass.printX();

静态成员也可以使用相同的公共、受保护和私有可见性修饰符,静态成员也会被继承。

class Base {private static x = 0;static getGreeting() {return "Hello world";}
}
class Derived extends Base {myGreeting = Derived.getGreeting();
}

name, length, 和call这些特殊的关键词不要定义为静态成员

类泛型

类和接口一样,可以是泛型的。当使用 new 实例化一个泛型类时,其类型参数的推断方式与函数调用相同。

class Box<Type> {contents: Type;constructor(value: Type) {this.contents = value;}
}const b = new Box("hello!");

this

重要的是要记住,TypeScript 不会改变 JavaScript 的运行时行为,而 JavaScript 因其某些特殊的运行时行为而闻名。

class MyClass {name = "MyClass";getName() {return this.name;}
}
const c = new MyClass();
const obj = {name: "obj",getName: c.getName,
};// Prints "obj", not "MyClass"
console.log(obj.getName());

js的this是运行时看的,谁调用this就是指的谁。

上面可以使用箭头函数让this指向类:

class MyClass {name = "MyClass";getName = () => {return this.name;};
}
const c = new MyClass();
const g = c.getName;
// Prints "MyClass" instead of crashing
console.log(g());

这样做有一定的代价:

  • 该值保证在运行时是正确的,即使是没有经过 TypeScript 检查的代码也是如此。
  • 这会占用更多内存,因为每个类实例都将拥有以这种方式定义的每个函数的副本
  • 不能在派生类中使用 super.getName,因为在原型链中没有条目可以从基类方法中获取
    或者使用this参数:
    在方法或函数定义中,名为 this 的初始参数在 TypeScript 中具有特殊意义。这些参数在编译时会被删除。
    TypeScript 会检查使用 this 参数调用函数的上下文是否正确。我们可以不使用箭头函数,而是在方法定义中添加 this 参数,静态地强制方法被正确调用。
class MyClass {name = "MyClass";getName(this: MyClass) {return this.name;}
}
const c = new MyClass();
// OK
c.getName();// Error, would crash
const g = c.getName;
console.log(g());

您可以在类和接口方法的返回位置使用此 Type。当与类型缩小(如 if 语句)混合使用时,目标对象的类型将缩小为指定的类型:

class FileSystemObject {isFile(): this is FileRep {return this instanceof FileRep;}isDirectory(): this is Directory {return this instanceof Directory;}isNetworked(): this is Networked & this {return this.networked;}constructor(public path: string, private networked: boolean) {}
}class FileRep extends FileSystemObject {constructor(path: string, public content: string) {super(path, false);}
}class Directory extends FileSystemObject {children: FileSystemObject[];
}interface Networked {host: string;
}const fso: FileSystemObject = new FileRep("foo/bar.txt", "foo");if (fso.isFile()) {fso.content;const fso: FileRep
} else if (fso.isDirectory()) {fso.children;} else if (fso.isNetworked()) {fso.host;}

构造参数属性

TypeScript 提供了特殊的语法,可将构造函数参数转化为具有相同名称和值的类属性。这些属性称为参数属性,通过在构造函数参数前添加 public、private、protected 或 readonly 可见性修饰符来创建。生成的字段将获得这些修饰符:

class Params {constructor(public readonly x: number,protected y: number,private z: number) {// No body necessary}
}
const a = new Params(1, 2, 3);
console.log(a.x);console.log(a.z);

类表达式声明

类表达式与类声明非常相似。唯一真正的区别是类表达式不需要名称,尽管我们可以通过它们最终绑定的标识符来引用它们:

const someClass = class<Type> {content: Type;constructor(value: Type) {this.content = value;}
};const m = new someClass("Hello, world");

类实例类型

JavaScript 类使用 new 运算符进行实例化。鉴于类本身的类型,InstanceType 实用程序类型可以模拟这种操作。

class Point {createdAt: number;x: number;y: numberconstructor(x: number, y: number) {this.createdAt = Date.now()this.x = x;this.y = y;}
}
type PointInstance = InstanceType<typeof Point>function moveRight(point: PointInstance) {point.x += 5;
}const point = new Point(3, 4);
moveRight(point);
point.x; // => 8

abstract 修饰符

TypeScript 中的类、方法和字段可以是抽象的。
抽象方法或抽象字段是一种尚未提供实现的方法或字段。这些成员必须存在于不能直接实例化的抽象类中。
抽象类的作用是为实现所有抽象成员的子类提供基类。当一个类没有任何抽象成员时,它就被称为具体类。
我们不能用 new 来实例化 Base,因为它是抽象的。相反,我们需要创建一个派生类并实现抽象成员:

abstract class Base {abstract getName(): string;printName() {console.log("Hello, " + this.getName());}
}// error
const b = new Base();
class Derived extends Base {getName() {return "world";}
}const d = new Derived();
d.printName();

类之间

在大多数情况下,TypeScript 中的类在结构上与其他类型相同。
例如,这两个类可以相互替代使用,因为它们完全相同:

class Point1 {x = 0;y = 0;
}class Point2 {x = 0;y = 0;
}// OK
const p: Point1 = new Point2();

同样,即使没有显式继承,类之间也存在子类型关系:

class Person {name: string;age: number;
}class Employee {name: string;age: number;salary: number;
}// OK
const p: Person = new Employee();

空类没有成员。**在结构类型系统中,没有成员的类型通常是其他任何类型的超类型。**因此,如果你编写了一个空类(不要!),那么任何东西都可以用来代替它:

class Empty {}function fn(x: Empty) {// can't do anything with 'x', so I won't
}// All OK!
fn(window);
fn({});
fn(fn);

不要这样写,没意义。

结语

结束了。

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

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

相关文章

MVC和Filter

目录 MVC和三层架构模型的联系 Filter 概念 作用 应用场景 步骤 简单入门 MVC和三层架构模型的联系 m-->model即模型是三层架构模型的业务层&#xff08;service&#xff09;和持久层(dao) v-->views即视图是三层架构模型的表现层(web) c-->controller即控制器也…

出现 java: Annotation processing is not supported for module cycles 解决方法

目录 前言1. 问题所示2. 原理分析3. 解决方法前言 对于循环依赖的问题,代码中遇到过两次,分别如下: 深度剖析Spring循环依赖(实战Bug)出现The dependencies of some of the beans in the application context form a cycle 解决方法(全)对于模块的依赖第一次遇到,如文…

【SpringMVC】_SpringMVC项目返回HTML与JSON

目录 1. SpringMVC项目返回HTML页面 2. SpringMVC项目返回JSON 2.1 程序演示 2.2 关于响应的Content-Type 2.2.1 接口为对象 2.2.2 接口为String 2.2.3 接口为Map 本专栏已介绍&#xff1a; 返回静态页面&#xff1a; 【Spring MVC】_SpringMVC项目返回静态页面_mvc 返…

一种基于高德Web API实现沿路画面的实现

概述 本文在mapboxGL框架下&#xff0c;分享一种基于高德Web API实现沿路画面的实现。 实现效果 实现 1. 实现思路 通过点击获取路径的起点和终点&#xff1b;将多次规划路径的结果连成一条线&#xff1b;当鼠标点击回到第一个点的时候结束绘制&#xff1b;绘制结束后将路径…

写代码之前一定要提前想好思路

就和写数学题目一样&#xff0c;在做题目之前要先把思路确立下来。可能是我早年做数学的时候老是着急做题目没怎么分析过题目&#xff0c;把这个习惯不自觉地代入了代码的写入当中。习惯的养成使得我即使明白了自己的问题也依然会不断的犯错&#xff0c;看来只有刻意地提醒自己…

Flutter 中的 Viewport 小部件:全面指南

Flutter 中的 Viewport 小部件&#xff1a;全面指南 Flutter 是一个现代的移动和 web 应用开发框架&#xff0c;它允许开发者以一种非常直观和高效的方式构建用户界面。在 Flutter 中&#xff0c;Viewport 是一个非常重要的小部件&#xff0c;它提供了一个滚动视口&#xff0c…

【MATLAB源码-第217期】基于matlab的16QAM系统相位偏移估计HOS算法仿真,对比补偿前后的星座图误码率。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 高阶统计量&#xff08;HOS&#xff09;频偏估计算法 高阶统计量&#xff08;Higher Order Statistics, HOS&#xff09;频偏估计算法是一种先进的信号处理技术&#xff0c;广泛应用于现代数字通信系统中&#xff0c;以应对…

【Nginx】深入解析Nginx配置文件

Nginx&#xff08;发音为“engine-ex”&#xff09;是一个高性能的HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP代理服务器。由于其高并发性、低资源消耗和模块化设计&#xff0c;Nginx在全球范围内被广泛使用。本文将深入解析Nginx配置文件&#xff0c;帮助读者了…

如何快速申请免费单域名SSL证书

申请免费的单域名SSL证书通常涉及以下几个步骤&#xff0c;虽然具体细节可能会根据不同的证书颁发机构(CA)有所差异。以下是通用的申请流程&#xff1a; 1.选择证书颁发机构&#xff1a; 访问提供免费单域名SSL证书的证书颁发机构网站&#xff0c;例如JoySSL等。 2.注册账号…

全局配置-案例:配置tabBar

一、需求&#xff1a;实现如图所示的tabBar效果 二、实现步骤&#xff1a; 1.拷贝图标资源 把image文件夹拷贝到小程序项目根目录中 图片中包含-active的是选中之后的图标 图片中不包含-active的是默认图标 2.新建3个对应的tab页面 3.配置tabBar选项 &#xff08;1&#xf…

oracle tree

select * from "Test"; INSERT INTO "Test" ("id", "name", "pid") VALUES (01, 中国, 00); INSERT INTO "Test" ("id", "name", "pid") VALUES (01.01, 福建, 01); INSERT INTO…

【MySQL】——数据库设计概述与需求分析

&#x1f4bb;博主现有专栏&#xff1a; C51单片机&#xff08;STC89C516&#xff09;&#xff0c;c语言&#xff0c;c&#xff0c;离散数学&#xff0c;算法设计与分析&#xff0c;数据结构&#xff0c;Python&#xff0c;Java基础&#xff0c;MySQL&#xff0c;linux&#xf…

如何找出真正的交易信号?Anzo Capital昂首资本总结7个

匕首是一种新兴的价格走势形态&#xff0c;虽然不常见&#xff0c;但具有较高的统计可靠性。它通常预示着趋势的持续发展。该模式涉及到同时参考两个不同的时间周期进行交易&#xff0c;一个是短期&#xff0c;另一个是长期&#xff0c;比如一周时间框架与一天时间框架、一天时…

看完这篇抖音小店选品秘籍!难道还愁不会选品吗?

大家好&#xff0c;我是喷火龙。 做抖音小店&#xff0c;没有什么花里胡哨的东西&#xff0c;核心就是我们的产品&#xff0c;把大部分精力用到选品上肯定是没错的。 选品之前一定要做好店铺的定位&#xff0c;确定好自己的主营类目&#xff0c;主营类目至少要占店铺产品的70…

Android--AOSP中使用AlertDialog使用踩坑记录

在App中使用AlertDialog有很多帖子说明&#xff0c;这里不在赘述。主要记录修改AOSP中遇到的使用AlertDialog踩坑记录。 在fwk中的service或者是CarService中要使用AlertDialog&#xff0c;仅添加AlertDialog是不够的&#xff0c;会直接crash。 android.view.WindowManager$B…

J.搬砖【蓝桥杯】/01背包+贪心

搬砖 01背包贪心 思路&#xff1a;要让重量更小的在更前面&#xff0c;价值更大的在更后面&#xff0c;vi−wj>vj−wi viwi>vjwj 第 i 个箱子放在第 j 个箱子下面就显然更优。所以进行排序再用01背包即可。 #include<iostream> #include<algorithm> #defi…

go语言的使用方法

一.go语言的介绍 1.简介 2.应用领域 3.使用go语言的公司 4.go语言开发工具介绍 5.go语言开发环境搭建 【1】搭建Go开发环境-安装和配置SDK 基本介绍: 1).SDK的全称(Software Development Kit软件开发工具包&#xff09;2).SDK是提供给开发人员使用的&#xff0c;其中包含了…

SAP 消息号VF501科目确定期间出错

在销售开票VF02的时候&#xff0c;经常出现报错&#xff1a;“科目确定期间出错”&#xff0c;这个报错&#xff0c;目前检查步骤&#xff1a; 1、BP客户主数据&#xff0c;销售代码层数据&#xff08;销售与分销&#xff09;-开票-会计-客户科目分配组&#xff0c;要与销售订…

【UML用户指南】-02-UML的14种图

1、结构图 1、类图&#xff08;class diagram&#xff09; 展现了一组类、接口、协作和它们之间的关系。 在面向对象系统的建模中所建立的最常见的图就是类图。类图给出系统的静态设计视图。 包含主动类的类图给出系统的静态进程视图。构件图是类图的变体。 2、对象图&a…

【ONE·Git || 基本用法入门】

总言 主要内容&#xff1a;主要介绍Git中常用的指令。   PS&#xff1a;多人协作与企业开发模型使用&#xff0c;此部分内容不作博文总结。             文章目录 总言1、初识Git1.1、版本控制器1.2、git安装 2、基本操作2.1、Git本地仓库2.1.1、创建Git本地仓库&…