TypeScript躬行记(3)——类

  类是对对象的抽象,描述了对象的特征和行为,而对象就是类的实例。ES6引入了类的概念(相关内容可参考ES类ES6类的继承两节),TypeScript在此基础上,不仅根据ES7等规范完善了类的语法,还添加了许多其它语法。而在使用TypeScript的类时,不必关心兼容性问题,因为这些工作已由编译器完成。

  下面是一个简单的类,包含3个成员:带private修饰符的name属性、构造函数constructor()和getName()方法,最后一句使用new运算符创建了Person类的实例,并调用了一次它的构造函数。

class Person {
  private name: string;
  constructor(name: string) {
    this.name = name;
  }
  getName() {
    return this.name;
  }
}
let worker = new Person("strick");

  编译后的代码如下所示,通过传统的构造函数和基于原型的继承来模拟一个类。

var Person = /** @class */ (function() {
  function Person(name) {
    this.name = name;
  }
  Person.prototype.getName = function() {
    return this.name;
  };
  return Person;
})();
var worker = new Person("strick");

一、属性

  在ES6中,实例属性(即自有属性)得作为this对象的属性存在,并且一般都会在构造函数中执行初始化,而TypeScript允许在类中直接定义实例属性,如下所示。

class Person {
  constructor(name: string) {
    this.name = name;
  }
}
//TypeScript中的实例属性
class Person {
  name: string;
}

  不仅如此,TypeScript还提供了存在于类本身上的静态属性,即不需要实例化就能调用的属性。在下面的示例中,为age属性添加了static关键字,使其成为静态属性,通过类的名称就能直接调用它。

class Person {
  static age: number;
}
Person.age = 28;

二、修饰符

  修饰符是用于限定成员或类型的一种符号,TypeScript包含三个访问修饰符:public、private和protected,以及一个成员修饰符:readonly。

1)public

  在TypeScript中,成员默认都是public的,即在派生类(也叫子类)或类的外部都能被访问。在下面的示例中,Person类中的name属性是公共的,Programmer类继承了Person类。注意,当派生类包含一个构造函数时,必须调用super()方法,执行基类(即父类)的构造函数,并且该方法得在访问this对象之前调用。

class Person {
  public name: string;
  constructor(name: string) {
    this.name = name;
  }
}
class Programmer extends Person {
  constructor(name: string) {
    super(name);
  }
}

  在初始化Person类或Programmer类之后,就能通过创建的实例来访问name属性,如下所示。

let person = new Person("strick");
person.name;            //"strick"
let programmer = new Programmer("freedom");
programmer.name;        //"freedom"

2)private

  当成员被修饰为private时,只能在类的内部访问它,例如在基类Person中声明一个私有的age属性,在类的实例或派生类的实例中访问age属性都会在编译阶段报错,如下所示。

class Person {
  private age: number;
}
person.age;            //错误
programmer.age;        //错误

  当构造函数被修饰为private时(如下所示),包含它的类既不能实例化,也不能被继承。

class Person {
  private constructor(name: string) {
    this.name = name;
  }
}

3)protected

  此修饰符与private的行为类似,只是有一点不同,即在派生类中还是可以访问它的,例如在基类Person中声明一个受保护的school属性,在派生类中就能访问到它,如下所示(省略了基类的构造函数)。

class Person {
  protected school: string;
}
class Programmer extends Person {
  constructor(name: string) {
    super(name);
    this.school = "university";
  }
}

  当构造函数被修饰为protected时(如下所示),包含它的类不能实例化,但可以被继承。

class Person {
  protected constructor(name: string) {
    this.name = name;
  }
}

4)readonly

  当成员被修饰为readonly时,它就变成只读的,只能在声明时或构造函数里初始化,其它地方对它的修改都是禁止的,如下所示。

class Person {
  readonly gender: string = "女";        //正确
  constructor() {
    this.gender = "男";                //正确
  }
}
let person = new Person();
person.gender = "女";                 //错误

  当readonly与其它修饰符一起使用时,需跟在它们后面,如下所示。

class Person {
  protected readonly gender: string;
}

三、参数属性

  参数属性可以便捷的在构造函数中声明并初始化一个类的属性,此类参数会与三个访问修饰符或readonly组合使用,如下所示。

class Person {
  constructor(public name: string) { }
}

  构造函数中的name是一个参数属性,相当于在Person类中声明一个name属性,并在构造函数中为其初始化,如下所示。

class Person {
  public name: string;
  constructor(name: string) {
    this.name = name;
  }
}

四、抽象类

  抽象类是供其它派生类继承的基类,它与接口一样,不能被实例化,但可以包含成员的实现细节。在声明一个类时,如果包含abstract关键字,那么这就是一个抽象类,如下所示,当对其进行实例化时,会在编译时报错。

abstract class Person { }
let person = new Person();        //错误

  在抽象类中,会声明一个或多个带abstract类修饰符的抽象方法,它们只有名称,不包含实现细节,可与访问修饰符组合使用,如下所示。

abstract class Person {
  protected abstract work(): void
}

  派生类中必须实现继承的抽象方法(如下所示),否则会在编译阶段报错。

class Programmer extends Person {
  public work(): void {
    console.log("code");
  }
}

原文地址:https://www.cnblogs.com/strick/p/11676023.html

时间: 2024-07-31 03:20:03

TypeScript躬行记(3)——类的相关文章

TypeScript躬行记(2)——接口

在传统的面向对象语言中,接口(Interface)好比协议,它会列出一系列的规则(即对行为进行抽象),再由类来实现这些规则.而TypeScript中的接口更加灵活,除了包含常规的作用之外,它还能扩展其它的类.为对象的类型命名以及约束值的结构等,大大消除了许多潜在的错误. 一.属性 TypeScript中的接口可通过声明属性和其类型来限制对象的结构.例如定义一个名为Person的接口,包含一个字符串类型的name属性和一个数字类型的age属性,如下所示. interface Person { na

TypeScript躬行记(7)——命名空间

TypeScript中的命名空间可将那些具有内在联系的接口.类或对象等代码组织在一起,既能隔离作用域,也能避免命名冲突,并且使得代码结构清晰,更易追踪.在命名空间内部,所有实体部分默认都是私有的,需要由export关键字导出之后,才能在外部访问,如下所示. namespace Util { export function log(msg) { console.log(msg); } } Util.log("strick"); TypeScript会将上面的命名空间编译成两部分:Util

CSS躬行记(2)——伪类和伪元素

一.伪类选择器 伪选择器弥补了常规选择器的不足,能够实现一些特殊情况下的样式,例如在鼠标悬停时或只给字符串中的第一个字符指定样式.与类选择器类似,可以从HTML元素的class属性中查看到,但伪选择器不会出现在HTML文档中(有几个例外,如:lang.::placeholder等).并且它的关键字大小写不敏感,也就是说empty和EMPTY完全相同.伪选择器分为两种:伪类选择器和伪元素选择器.注意,伪选择器会以一个或两个冒号(:)开头,并且如果要与其它选择器组合使用,那么只能与类型选择器(即元素

ES6躬行记(7)——代码模块化

在ES6之前,由于ECMAScript不具备模块化管理的能力,因此往往需要借助第三方类库(例如遵守AMD规范的RequireJS或遵循CMD规范的SeaJS等)才能实现模块加载.而自从ES6引入了模块化标准后,就不需要再特地加载一次外部脚本了.模块化的语法不仅让JavaScript代码的组织变得更有条理,还包含封装.按需导出或导入等实用功能,可轻松应对日益复杂和庞大的前端工程.但有一点要注意,模块中的代码默认运行在严格模式中. 一.导出 一个模块就是一个独立的JavaScript文件,如果要读取

React躬行记(5)——React和DOM

React实现了一套与浏览器无关的DOM系统,包括元素渲染.节点查询.事件处理等机制. 一.ReactDOM 自React v0.14开始,官方将与DOM相关的操作从React中剥离,组成单独的react-dom库,从而让React能兼容更多的终端.在引入react-dom库后,就能调用一个全局对象:ReactDOM,虽然在之前的章节中已多次使用该对象,但是都没有给出过多的讲解,本节将对其做重点分析. ReactDOM只包含了unmountComponentAtNode().findDOMNod

Vue躬行记(3)——样式和表单

Vue对DOM元素的class和style两个特性做了专门的增强,即对CSS类和内联样式做了一层封装,通过v-bind指令来处理它们,而接收的表达式既可以是简单的字符串.对象或数组,也可以是复杂的计算属性.不仅如此,Vue还为表单设计了一些语法糖,让表单处理变得尤为简单. 一.CSS类 v-bind指令与class参数配合,就能处理CSS类,并且能接收多种类型的值. 1)对象 v-bind:class可以接收一个对象,对象的属性名就是CSS类名,只有当其值是真值时,才能添加到DOM元素上,否则会

CSS躬行记(1)——CSS基础拾遗

一.box-decoration-break CSS3新增的box-decoration-break属性可指定行内非替换元素在跨行.跨列或跨页时的样式渲染,它包含两个值: (1)slice:默认值,盒子会被分割成多部分. (2)clone:断开的各个盒子会单独渲染. 下面用一个示例来演示两种的区别,第一个span元素采用box-decoration-break的默认值,效果如第一张图所示,在断行处没有左右内边距和圆角:第二个span元素box-decoration-break的值为clone,效

ES6躬行记(2)——扩展运算符和剩余参数

扩展运算符(Spread Operator)和剩余参数(Rest Parameter)的写法相同,都是在变量或字面量之前加三个点(...),并且只能用于包含Symbol.iterator属性的可迭代对象(iterable).虽然两者之间有诸多类似,但它们的功能和应用场景却完全不同.扩展运算符能把整体展开成个体,常用于函数调用.数组或字符串处理等:而剩余参数正好相反,把个体合并成整体,常用于函数声明.解构参数等.此处的整体可能是数组.字符串或类数组对象等,个体可能是字符.数组的元素或函数的参数等.

React躬行记(7)——表单

表单元素是一类拥有内部状态的元素,这些状态由其自身维护,通过这类元素可让用户与Web应用进行交互.HTML中的表单元素(例如<input>.<select>和<radio>等)在React中都有相应的组件实现,不仅如此,React还将它们分成两种:受控组件和非受控组件. 一.受控组件 受控组件(Controlled Component)是指那些受React控制的表单元素,其状态(value.checked等属性)的变更由组件的state管理.对于不同的表单元素,其受控组