当前位置:网站首页>LayaBox---TypeScript---类
LayaBox---TypeScript---类
2022-07-30 17:38:00 【格拉格拉】
目录
1.普通类的示例
class Greeter{
greeting: string;
constructor(msg: string){
this.greeting = msg;
}
greet(){
return "hello, " + this.greeting;
}
}
let greeter = new Greeter("world");
2.继承
//一个简单的继承示例
class Animal{
move( distanceInMeters: number=0 ){
console.log('Animal moved ${distanceInMeters}m.');
}
}
class Dog extends Animal{
bark(){
console.log( 'Woof! Woof!' );
}
}
Const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
//一个复杂的继承示例
class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 45) {
console.log("Galloping...");
super.move(distanceInMeters);
}
}
let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
与前一个简单的继承示例不同的是,它的派生类包含了一个构造函数,它必须调用super(),它会执行基类的构造函数。
️注意:在构造函数里访问this的属性前,一定要调用supper()。这是ts强制执行的一条规则。
3.公共、私有与受保护的修饰符
3.1 与C#等语言不同,ts里成员默认都是public属性
public:
//也可以明确的将成员标记成public
class Animal {
public name: string;
public constructor(theName: string) { this.name = theName; }
public move(distanceInMeters: number) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
private:
//当成员被标记成 private 时,它就不能在声明它的类的外部访问
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // 错误: 'name' 是私有的.
TypeScript使用的是结构性类型系统。 当我们比较两种不同的类型时,并不在乎它们从何处而来,如果所有成员的类型都是兼容的,我们就认为它们的类型是兼容的。
然而,当我们比较带有 private
或 protected
成员的类型的时候,情况就不同了。 如果其中一个类型里包含一个 private
成员,那么只有当另外一个类型中也存在这样一个 private
成员, 并且它们都是来自同一处声明时,我们才认为这两个类型是兼容的。 对于 protected
成员也使用这个规则。
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
class Rhino extends Animal {
constructor() { super("Rhino"); }
}
class Employee {
private name: string;
constructor(theName: string) { this.name = theName; }
}
let animal = new Animal("Goat");
let rhino = new Rhino();
let employee = new Employee("Bob");
animal = rhino;
animal = employee; // 错误: Animal 与 Employee 不兼容.
protected:
protected
修饰符与 private
修饰符的行为很相似,但有一点不同, protected
成员在派生类中仍然可以访问。
class Person {
protected name: string;
constructor(name: string) { this.name = name; }
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name)
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误
注意,我们不能在 Person类外使用 name,但是我们仍然可以通过 Employee类的实例方法访问,因为 Employee是由 Person派生而来的。
构造函数也可以被标记成 protected
。 这意味着这个类不能在包含它的类外被实例化,但是能被继承。
class Person {
protected name: string;
protected constructor(theName: string) { this.name = theName; }
}
// Employee 能够继承 Person
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
let howard = new Employee("Howard", "Sales");
let john = new Person("John"); // 错误: 'Person' 的构造函数是被保护的.
4.readonly修饰符
可以使用 readonly
关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。
class Octopus {
readonly name: string;
readonly numberOfLegs: number = 8;
constructor (theName: string) {
this.name = theName;
}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
上面的例子,我们在Octopus里定义了一个只读成员name和一个参数为theName的构造函数,且将theName的值赋给了name。
而参数属性可以方便的让我们在一个地方定义并初始化成员。
class Octopus {
readonly numberOfLegs: number = 8;
constructor(readonly name: string) {
}
}
如上,我们是如何舍弃了 theName
,仅在构造函数里使用 readonly name: string
参数来创建和初始化 name
成员。 我们把声明和赋值合并至一处。
5.存取器
TypeScript支持通过getters/setters来截取对对象成员的访问。
class Employee {
fullName: string;
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
console.log(employee.fullName);
}
下面这个版本里,我们先检查用户密码是否正确,然后再允许其修改员工信息。 我们把对 fullName
的直接访问改成了可以检查密码的 set
方法。 我们也加了一个 get
方法,让上面的例子仍然可以工作。
let passcode = "secret passcode";
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (passcode && passcode == "secret passcode") {
this._fullName = newName;
}
else {
console.log("Error: Unauthorized update of employee!");
}
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
alert(employee.fullName);
}
️注意:
1.存取器要求你将编译器设置为输出ECMAScript 5或更高。 不支持降级到ECMAScript 3。
2.只带有 get
不带有 set
的存取器自动被推断为 readonly
。
6.静态属性--static
我们使用 static
定义 origin
,因为它是所有网格都会用到的属性。 每个实例想要访问这个属性的时候,都要在 origin
前面加上类名。 如同在实例属性上使用 this.
前缀来访问属性一样
class Grid {
static origin = {x: 0, y: 0};
calculateDistanceFromOrigin(point: {x: number; y: number;}) {
let xDist = (point.x - Grid.origin.x);
let yDist = (point.y - Grid.origin.y);
return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
}
constructor (public scale: number) { }
}
let grid1 = new Grid(1.0); // 1x scale
let grid2 = new Grid(5.0); // 5x scale
console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
7.抽象类--abstract
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。
1.不同于接口,抽象类可以包含成员的实现细节。
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log('roaming the earch...');
}
}
2.抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。
3.抽象方法必须包含 abstract
关键字并且可以包含访问修饰符。
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log('Department name: ' + this.name);
}
abstract printMeeting(): void; // 必须在派生类中实现
}
class AccountingDepartment extends Department {
constructor() {
super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
}
printMeeting(): void {
console.log('The Accounting Department meets each Monday at 10am.');
}
generateReports(): void {
console.log('Generating accounting reports...');
}
}
let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在
8.把类当作接口使用
class Point {
x: number;
y: number;
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};
边栏推荐
猜你喜欢
un7.30:Linux——如何在docker容器中显示MySQL的中文字符?
Analysis and Simulation of Short Circuit Fault in Power System Based on MATLAB
ERROR 2003 (HY000) Can‘t connect to MySQL server on ‘localhost3306‘ (10061)解决办法
MySQL中的存储过程(详细篇)
JVM诊断命令jcmd介绍
SYSCALL SWAPGS
基于亚马逊云科技无服务器服务快速搭建电商平台——性能篇
如何让 JOIN 跑得更快?
bean的生命周期
952. 按公因数计算最大组件大小 : 枚举质因数 + 并查集运用题
随机推荐
(17)[系统调用]追踪系统调用(0环)
【Cloud Store Announcement】Notice of Help Center Update on July 30
主流的深度学习推理架构有哪些呢?
WeChat applet picker scroll selector use detailed explanation
Error EPERM operation not permitted, mkdir 'Dsoftwarenodejsnode_cache_cacach Two solutions
高级语言垃圾回收思路和如何减少性能影响原理分析
华为无线设备配置Mesh业务
Logback的使用
今年这情况。。真心推荐专科的工程师升个本!
将 APACHE 日志解析到 SQL 数据库中
What is NDT equipment?
C陷阱与缺陷 第7章 可移植性缺陷 7.4 字符是有符号数还是无符号数
Error occurred while trying to proxy request The project suddenly can't get up
查询表中开始日期与结束日期
weiit新零售小程序如何探索数字化门店的破局之路
MySQL中的存储过程(详细篇)
Test the.net text to Speech module System. Researched
C陷阱与缺陷 第6章 预处理器 6.4 宏并不是类型定义
数据库系统原理与应用教程(063)—— MySQL 练习题:操作题 39-50(七):SELECT 基本语法联系
公司部门来了个00后测试卷王之王,老油条表示真干不过,已经...