TypeScript 类
ts 中 class 与 ES6 使用方式一致
修饰符
- public:默认值,公开的外部也可以访问
- protected:类内部和子类可以访问,类外部没法访问
- private:只能类内部访问 子类和外部没法访问
- readonly:只读的属性,必须在声明和构造函数中初始化,可以和前面关键字搭配使用
public
默认值,公有属性
ts
class Person {
public name: string; /* 公有属性 */
constructor(name: string){
this.name = name;
}
getName():string{ /* 默认 public 公有属性 */
return this.name;
}
}
console.log(new Person('tom').name); // tom
console.log(new Person('tom').getName()); // tom
class Son extends Person{
constructor(name:string){
super(name)
}
getName(): string {
return `这是子类:${this.name}`
}
}
console.log(new Son('son').name); // son
console.log(new Son('son').getName()); // 这是子类:son
protected
类内部和子类可以访问,类外部没法访问
ts
class Person {
protected name: string;
constructor(name: string){
this.name = name;
}
getName():string{
return this.name;
}
}
console.log(new Person('tom').name); // 编译器报错:属性“name”受保护,只能在类“Person”及其子类中访问。
console.log(new Person('tom').getName()); // tom
class Son extends Person{
constructor(name:string){
super(name)
}
}
console.log(new Son('son').name); // 编译器报错:属性“name”受保护,只能在类“Person”及其子类中访问。
console.log(new Son('son').getName()); // son
private
只能类内部访问
ts
class Person {
private name: string;
constructor(name: string){
this.name = name;
}
getName():string{
return this.name;
}
}
console.log(new Person('tom').name); // 编译器报错:属性“name”受保护,只能在类“Person”及其子类中访问。
console.log(new Person('tom').getName()); // tom
class Son extends Person{
constructor(name:string){
super(name)
}
getName():string{
return this.name; // 报错:属性“name”为私有属性,只能在类“Person”中访问。
}
}
console.log(new Son('son').name); // 编译器报错:属性“name”受保护,只能在类“Person”及其子类中访问。
readonly
ts
class Person {
readonly name: string;
constructor(name: string){
this.name = name;
}
setName(){
this.name = 'a' // 错误:无法分配到 "name" ,因为它是只读属性。
}
}
new Person('tom').name = 1; // 错误:无法分配到 "name" ,因为它是只读属性。
class Son extends Person{
constructor(name:string){
super(name)
}
}
new Son('son').name = 2 // 错误:无法分配到 "name" ,因为它是只读属性。
- 参数属性
ts
class Octopus {
constructor(readonly num: number,public readonly n: string) {
// this.num = num
}
setNum(){
this.num = 3; // 无法分配到 "num" ,因为它是只读属性。
this.n = 3; // 无法分配到 "n" ,因为它是只读属性。
}
}
存取器
类里面可以使用 getter、setter
ts
class Person {
private _name = 'tom';
get name():string{
console.log('get');
return this._name
}
set name(name:string){
console.log('set');
this._name = name
console.log(this._name);
}
}
console.log(new Person().name);
new Person().name = 'test'
静态属性
ts 静态属性与 ES6 一致
ts
class Person {
static age:number = 100;
}
Person.age // 100
new Person().age // 不存在
抽象类
B继承A:
- B ---> 子类[派生类]
- A ---> 超类[基类、父类]
abstract 关键字表示抽象类(父类),加了 abstract 关键字的方法必须被派生类(子类)继承且实现,不加 abstract 的方法可以不用实现。
ts
/* 父类(抽象类、基类),不会直接被实例化 */
abstract class Person {
constructor(public name: string,public age: number){}
/* 子类(派生类必须实现此方法),父类不包含具体实现 */
abstract getName(num: number):void;
/* 没有 abstract 子类可以不用实现 */
getAge(){
console.log(this.age,'抽象类');
}
}
class Son extends Person{
constructor(){
super('tom',10) // 子类存在构造器时必须调用 super 方法
}
/* 实现父类 getName */
getName(num: number): void{
console.log(num + this.age);
}
myFn(){
console.log('myFn');
}
}
new Person(); // 错误 抽象类无法实例化
let p: Person; // 可以创建引用
p = new Son() // 允许子类实例化和赋值
p.getName(1) // ok
p.getAge() // ok
p.myFn(); // 错误:抽象类没有定义
高级技巧
引用 class 声明
ts
class Person {
static standardGreeting = "Hello";
greet(): string {
return Person.standardGreeting;
}
}
let person: Person = new Person(); // person: Person 需要赋值为 Person 的实例
console.log(person.greet()); // Hello
let newPerson: typeof Person = Person; // 相当于 let newPerson: Person 本身 = Person;
/* 这样就可以在新的引用 newPerson 上使用*/
newPerson.standardGreeting = "Hey";
let person1: Person = new newPerson();
console.log(person1.greet()); // Hey
接口继承类
ts
class _2D {
x: number | undefined;
y: number | undefined;
}
interface _3D extends _2D {
z: number;
}
let point: _3D = { x: 1, y: 2, z: 3 };