# 类
typescript
里的类和 javascript
里的类基本一样。 typerscript
扩展了类,它可以通过先声明的方式限制实例属性的类型,并且还引入了类似 C++
、 Java
的继承权限设定,拥有 public
、 protect
、 private
三种修饰符。若不声明权限则默认为 public
修饰符 | 外部访问 | 派生类访问 | 自身访问 |
---|---|---|---|
public | √ | √ | √ |
protected | × | √ | √ |
private | × | × | √ |
# public
public
修饰的属性可以在外部访问,也可以在派生类和自身实例中访问
class Person { | |
name: string | |
age: number | |
constructor(name:string, age:number) { | |
this.name = name | |
this.age = age | |
} | |
say(): void { | |
console.log(`My name is ${this.name},I'm ${this.age} years old`) | |
} | |
} | |
class Student extends Person { | |
course: string | |
constructor(name:string, age:number, course:string) { | |
super(name, age) | |
this.course = course | |
} | |
say() { | |
super.say() | |
console.log(`My course is ${this.course}`) | |
} | |
} | |
let man1: Person = new Person('sphinx', 16) | |
console.log(man1.name) // sphinx | |
man1.say() // My name is sphinx,I'm 16 years old | |
let man2: Student = new Student('asuhe', 16, 'math') | |
man2.say() // My name is asuhe,I'm 16 years old | |
// My course is math |
# protected
protected
修饰的属性不可以在外部访问,但可以在派生类和自身实例中访问
class Person { | |
protected name: string | |
protected age: number | |
constructor(name: string, age: number) { | |
this.name = name | |
this.age = age | |
} | |
say(): void { | |
console.log(`My name is ${this.name},I'm ${this.age} years old`) | |
} | |
} | |
class Student extends Person { | |
course: string | |
constructor(name: string, age: number, course: string) { | |
super(name, age) | |
this.course = course | |
} | |
say() { | |
super.say() | |
console.log(`My course is ${this.course}`) | |
} | |
} | |
let man1: Person = new Person('sphinx', 16) | |
console.log(man1.name) // error | |
man1.say() // My name is sphinx,I'm 16 years old | |
let man2: Student = new Student('asuhe', 16, 'math') | |
man2.say() // My name is asuhe,I'm 16 years old | |
// My course is math |
# private
protected
修饰的属性仅能自身实例中访问
class Person { | |
private name: string | |
private age: number | |
constructor(name: string, age: number) { | |
this.name = name | |
this.age = age | |
} | |
say(): void { | |
console.log(`My name is ${this.name},I'm ${this.age} years old`) | |
} | |
} | |
let man1: Person = new Person('sphinx', 16) | |
console.log(man1.name) // error | |
console.log(man1.age) // error | |
man1.say() // My name is sphinx,I'm 16 years old |
# readonly vs 权限修饰符
当我们希望一个属性仅可自身访问且仅可读取时,可以和 readonly
修饰符一起使用
class Goods { | |
public readonly id:number | |
constructor(id:number){ | |
this.id = id | |
} | |
} |
# 存取器
TypeScript
支持通过 getters/setters
来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
下面来看如何把一个简单的类改写成使用 get
和 set
。 首先,我们从一个没有使用存取器的例子开始。
class Person { | |
firstName: string = 'A' | |
lastName: string = 'B' | |
get fullName () { | |
return this.firstName + '-' + this.lastName | |
} | |
set fullName (value) { | |
const names = value.split('-') | |
this.firstName = names[0] | |
this.lastName = names[1] | |
} | |
} | |
const p = new Person() | |
console.log(p.fullName) | |
p.firstName = 'C' | |
p.lastName = 'D' | |
console.log(p.fullName) | |
p.fullName = 'E-F' | |
console.log(p.firstName, p.lastName) |
# 抽象类
抽象类做为其它派生类的基类使用。 ** 它们不能被实例化。** 不同于接口,抽象类可以包含成员的实现细节。 abstract
关键字是用于定义抽象类和在抽象类内部定义抽象方法。
/* | |
抽象类 | |
不能创建实例对象,只有实现类才能创建实例 | |
可以包含未实现的抽象方法 | |
*/ | |
abstract class Animal { | |
abstract cry () | |
run () { | |
console.log('run()') | |
} | |
} | |
class Dog extends Animal { | |
cry () { | |
console.log('Dog cry()') | |
} | |
} | |
const dog = new Dog() | |
dog.cry() // Dog cry() | |
dog.run() // run() |
# 抽象类 vs 接口
接口可以理解为里面所有属性都是 abstract
,而且使用了接口的类必须按接口的规格实现。接口的函数只能是定义,不能有函数体不能实现。
抽象类里的函数方法可以为 abstract
也可以不为 abstract
,而且抽象类的函数方法可以有函数体能够去实现。若抽象类的函数方法被实现类重写了,那么在实现类调用该方法时会调用实现类重写的那个方法。