TS类
在TS中声明了一个类的时候,实际上声明了两个东西
一个是创建了 类的实例的类型
一个是创建了 一个叫构造函数的值
这个 构造函数 会在创建类实例的时候被调用
如何定义类
存取器 构造函数
class User {
private myName:string;
constructor(myName: string) { // 构造函数,初始化成员属性
this.myName = myName;
}
get name() { // 存取器,用于修改类中属性,
return this.myName;
}
set name(value) {
this.myName = value;
}
}
// 存取器只有get 没有set 的private属性,会被自动推断为readonly
类 编译结果
static挂载在函数对象上
get/set挂载在原型对象上
public/private/protected 挂载在实例对象上
get/set 属性 不可和 public/private/protected 重名,可以和 static 重名
get/set 属性 编译的target 必须是 ES5及以上
class Animal1 {
static type = "1";
public type2 = "1"
private type3 = "1";
protected type4 = "1";
get type5() {
return "1"
}
}
const a = new Animal1()
var Animal1 = /** @class */ (function () {
function Animal1() {
this.type2 = "1";
this.type3 = "1";
this.type4 = "1";
}
Object.defineProperty(Animal1.prototype, "type5", {
get: function () {
return "1";
},
enumerable: false,
configurable: true
});
Animal1.type = "1";
return Animal1;
}());
修饰符
public: 默认,可以在任何地方使用
private: 不可为声明的类的外部访问
protected: 在自己和子类中可以访问,其他地方不可以访问
省略属性的声明
实例上的属性需要先声明在使用
在 构造函数 参数 前添加修饰符,可省略属性的声明
class User2 {
constructor(public myName: string) {}
get name() {
return this.myName;
}
set name(value) {
this.myName = value;
}
}
let user = new User2('lzy');
console.log(user.name);
readonly
readonly 修饰的变量 只能在构造函数中初始化
readonly 在编译时被检查 const 在运行时被检查
兼容性
在TS中,
正常情况 Animal类 的变量 可接收 Employee类型的数据,
因为他们类型检查一样(二者都有且仅有name,且假设二者的name是public)
但是,比较类型的时候, 如果出现了 private/protected成员,
则同时需满足 另一个类也存在这样一个private成员, 且来自于同一处.
public修饰的成员则不要求来自同一处
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 不兼容.
// 尽管Employee里也有一个私有成员name,但它明显不是Animal里面定义的那个
继承
子类 构造函数 必须使用 super() 以执行父类的构造函数
class Person {
name: string;//定义实例的属性,默认省略public修饰符
age: number;
constructor(name:string,age:number) {//构造函数
this.name=name;
this.age=age;
}
getName():string {
return this.name;
}
setName(name:string): void{
this.name=name;
}
}
class Student extends Person{
no: number;
constructor(name:string,age:number,no:number) {
super(name,age);
this.no=no;
}
getNo():number {
return this.no;
}
}
let s1=new Student('lzy',25,1);
console.log(s1);
静态属性和静态方法
静态属性 一般代表所有实例会共同用到的 属性
可通过 类.静态 类的实例.静态 访问
不需要 创建类实例可直接获取
class Father {
static className='Father';
static getClassName() {
return Father.className;
}
public name: string;
constructor(name:string) {//构造函数
this.name=name;
}
}
console.log(Father.className);
console.log(Father.getClassName());
抽象类
作为其他派生类的基类使用,代表一种抽象的概念.
无法被实例化,只能被继承.
抽象类中的抽象方法,不能在抽象类中实现,
只能在派生类中实现,且必须在派生类中实现.
一般不会被直接实例化.
抽象方法 和 接口方法 都定义方法前面 当不包含方法体.
不同于接口,抽象类可以包含成员的实现细节.
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(); // 错误: 方法在声明的抽象类中不存在
类装饰器
装饰器是一种特殊类型的声明,
它能够被附加到类声明、方法、属性或参数上,可以修改类的行为
常见的装饰器有 类装饰器 属性装饰器 方法装饰器 参数装饰器
装饰器的写法分为普通装饰器和装饰器工厂