ES6 中类的用法
下面我们先回顾一下 ES6 中类的用法,更详细的介绍可以参考 ECMAScript 6 入门 - Class
属性和方法
使用 class
定义类,使用 constructor
定义构造函数。
通过new
生成新实例的时候,会自动调用构造函数。
class Person{
constructor(name) {
this.name = name;
}
sayHi() {
return `My name is ${this.name}`;
}
}
let a = new Person('Jack');
console.log(a.sayHi()); // My name is Jack
类的继承
使用 extends
关键字实现继承,子类中使用 super
关键字来调用父类的构造函数和方法。
class Student extends Person {
constructor(name) {
super(name); // 调用父类的 constructor(name)
console.log(this.name);
}
sayHi() {
return 'Hello, ' + super.sayHi(); // 调用父类的 sayHi()
}
}
let c = new Student('Tom'); // Tom
console.log(c.sayHi()); // Hello, My name is Tom
静态方法
使用 static
修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用
class Foo {
static classMethod() {
return 'hello'
}
}
let a = Foo.classMethod()
console.log(a) // 'hello'
var foo = new Foo()
foo.classMethod()
// TypeError: foo.classMethod is not a function
实例属性
ES6 中实例的属性只能通过构造函数中的 this.xxx 来定义,ES7 提案中可以直接在类里面定义
class Person {
name = 'zs'
constructor() {
// ...
}
}
let a = new Person()
console.log(a.name) // zs
静态属性
指的是 Class 本身的属性,即Class.propName
,而不是定义在实例对象(this
)上的属性
class Person {
static age = 18
constructor() {
// ...
}
}
console.log(Person.age) // 18
TypeScript 中类的用法
定义变量
在TypeScript是不允许直接在constructor
定义变量的 需要在constructor
上面先声明
类的修饰符
- public(公共)
public
修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是public
的 - private(私有)
private
修饰的属性或方法是私有的,不能在声明它的类的外部访问 - protected(受保护)
protected
修饰的属性或方法是受保护的,它和private
类似,区别是它在子类中是允许被访问的
class Person {
public name:string
private age:number
protected gender:string|number
public constructor(name:string,age:number,gender:string|number) {
this.name = name;
this.age = age;
this.gender = gender
}
}
let zs = new Person('zs',18,'M')
zs.age // error:属性“age”为私有属性,只能在类“Person”中访问
zs.gender // error:属性“gender”受保护,只能在类“Person”及其子类中访问
class Person {
public name: string
private age: number
protected gender: string | number
public constructor(name: string, age: number, gender: string | number) {
this.name = name
this.age = age
this.gender = gender
}
}
class Man extends Person {
constructor() {
super('zs', 18, 'M')
// 子类可以访问到
console.log(this.gender) // M
}
}
let person = new Person('ls', 20, 'M')
let man = new Man()
man.gender // error: 属性“gender”受保护,只能在类“Person”及其子类中访问
参数属性
修饰符和readonly
还可以使用在构造函数参数中,等同于类中定义该属性同时给该属性赋值,使代码更简洁
class Person {
// public name: string;
constructor(public name: string) {
// this.name = name;
}
}
let p = new Person('zs')
console.log(p.name) // zs
readonly
只读属性关键字,只允许出现在属性声明或索引签名或构造函数中
class Person {
readonly name: string
public constructor(name: string) {
this.name = name
}
}
let a = new Person('Jack')
console.log(a.name) // Jack
// a.name = 'Tom' // error: 无法分配到 "name" ,因为它是只读属性
注意如果 readonly
和其他访问修饰符同时存在的话,需要写在其后面
class Person {
// readonly name: string
public constructor(public readonly name: string) {
// this.name = name
}
}
let a = new Person('Jack')
console.log(a.name) // Jack
抽象类
abstract
用于定义抽象类和其中的抽象方法。
首先,抽象类是不允许被实例化的
abstract class Person {
name: string
constructor(name: string) {
this.name = name
}
abstract init(name: string): void
}
let p = new Person('zs') // error 无法创建抽象类的实例
其次,抽象类中的抽象方法必须被子类实现
abstract class Person {
name: string
constructor(name: string) {
this.name = name
}
abstract init(name: string): void
}
class Man extends Person {
constructor(name: string) {
super(name)
}
init(name: string): void {
console.log(name)
}
}
let zs = new Man('zs')
zs.init('ls')
interface定义类
类只能继承(extends
)类,实现(implements
)接口
类可以实现接口或类,类不可以继承接口,类只能继承类
接口不能实现接口或者类,可以继承接口或类
可多继承或者多实现
interface PersonOne {
age: number
}
interface PersonTwo{
gender: string
}
class A {
name: string
constructor() {
this.name = "123"
}
}
class Person extends A implements PersonOne,PersonTwo {
age: number
gender:string
constructor() {
super()
this.age = 18
this.gender = 'M'
}
}