这是我参与更文挑战的第九天,活动详情查看:更文挑战
无论 ES 还是 TS 中, 类成员都是实例属性,类成员方法都是实例方法
一. TS 中 class 的特点
class Dog {
constructor(name: string) {
this.name = name;
}
name: string;
run() {}
}
复制代码
console.log(Dog.prototype);
// {run: ƒ, constructor: ƒ}
/*
打印出类的原型,
结果是不包含类的成员的, 只有 run(), constructor()
*/
复制代码
1.1 成员属性只在实例上, 而不在原型上
let dog = new Dog("大黄");
console.log(dog);
// Dog {name: "大黄"}
/*
可以看出name属性只在实例上, 而不在原型上
*/
复制代码
2.1 实例的属性必须具有初始值,或者在构造函数中被初始化
class Dog1 {
constructor(name: string) {
// this.name = name;
}
// 错误提示: 属性“name”没有初始化表达式,且未在构造函数中明确赋值。ts(2564)
name: string;
run() {}
}
复制代码
解决
class Dog1 {
constructor(name: string) {
// this.name = name;
}
name: string = "dog";
run() {}
}
// 或者
class Dog2 {
constructor(name: string) {
this.name = name;
}
name: string;
run() {}
}
复制代码
二. 类的继承
class Cat0 extends Dog {
//错误提示: 派生类的构造函数必须包含 "super" 调用。ts(2377)
constructor() {}
}
复制代码
解决 super
代表父类的实例
class Cat extends Dog {
constructor(name: string, color: string) {
super(name);
this.color = color;
}
color: string;
}
复制代码
三. 类的成员修饰符
1. 共有成员-public
类的所有属性默认都是 public,当然也可以直接申明出来
class Dog1 {
constructor(name: string) {
// this.name = name;
}
public name: string = "dog";
run() {}
}
复制代码
2. 私有成员-private
私有成员只能被类本身调用,而不能被类的实例调用,有不能被子类调用
class Dog {
constructor(name: string) {
this.name = name;
}
public name: string;
run() {}
private walk() {}
}
let dog = new Dog("大黄");
// 错误提示: 属性“walk”为私有属性,只能在类“Dog”中访问。ts(2341)
dog.walk();
class Cat extends Dog {
constructor(name: string, color: string) {
super(name);
this.color = color;
// 错误提示: 属性“walk”为私有属性,只能在类“Dog”中访问。ts(2341)
this.walk = () => {};
}
color: string;
}
复制代码
可以给构造函数添加私有成员属性,表示该类既不能被实例化,也不能被继承
class Dog {
private constructor(name: string) {
this.name = name;
}
public name: string;
run() {}
private walk() {}
}
// 错误提示: 类“Dog”的构造函数是私有的,仅可在类声明中访问。ts(2673)
let dog = new Dog("大黄");
// 错误提示: 无法扩展类“Dog”。类构造函数标记为私有。ts(2675)
class Cat extends Dog {
constructor(name: string, color: string) {
super(name);
this.color = color;
}
color: string;
}
复制代码
3. 受保护成员-protect
受保护成员只能在类及其子类中访问, 而不能再类的实例中访问
class Dog {
constructor(name: string) {
this.name = name;
}
public name: string;
protected shout() {}
}
let dog = new Dog("大黄");
// 错误提示: 属性“shout”受保护,只能在类“Dog”及其子类中访问。ts(2445)
dog.shout();
class Cat extends Dog {
constructor(name: string, color: string) {
super(name);
this.color = color;
// 可以正常访问和执行
this.shout();
}
color: string;
}
复制代码
可以给构造函数添加受保护成员属性,表示该类不能被实例化,只能被继承,相当于申明一个基类
4. 只读属性
只读属性表示不能被更改,并且一定要被初始化
class Dog {
constructor(name: string) {
this.name = name;
}
public name: string;
readonly foots: number = 4;
}
复制代码
5. 静态成员-static
类的静态成员只能通过类名来调用,二不能通过子类调用
class Dog {
constructor(name: string) {
this.name = name;
}
public name: string;
static food = "bones";
}
let dog = new Dog("大黄");
// bones
console.log(Dog.food);
// 错误提示: 属性 "food" 不是类型为 "Dog" 的静态成员ts(2576)
console.log(dog.food);
复制代码
类的静态成员也可以被继承
class Dog {
constructor(name: string) {
this.name = name;
}
public name: string;
static food = "bones";
}
class Cat extends Dog {
constructor(name: string, color: string) {
super(name);
this.color = color;
}
color: string;
}
// bones
console.log("Cat.food :", Cat.food);
复制代码
ES 中并没有抽象类的概念,TS 对此进行了扩展
抽象类
抽象类: 只能被继承,不能被实例化的类
abstract class Animal {
constructor() {}
}
// 无法创建抽象类的实例。ts(2511)
let animal = new Animal();
复制代码
可以在抽象类中定义一个具体的方法并有相关实现 这样子类就可以直接使用,而不用重复实现---实现了方法的复用
abstract class Animal {
constructor() {}
eat() {
console.log("eat");
}
}
class Pig extends Animal {
constructor(name: string) {
super();
this.name = name;
}
public name: string;
static food = "bones";
}
let pig = new Pig("佩奇");
pig.eat();
复制代码
多态
可以在抽象类中定义一个方法但不具体实现,形成一个抽象方法 **抽象方法的好处是可以在子类中有多种方式实现, **
abstract class Animal {
constructor() {}
abstract sleep(): void;
}
class Pig extends Animal {
constructor(name: string) {
super();
this.name = name;
}
public name: string;
sleep() {
console.log("站着睡");
}
}
let pig = new Pig("佩奇");
pig.sleep();
class Cat extends Animal {
sleep() {
console.log("趴着睡");
}
}
let cat = new Cat();
cat.sleep();
复制代码
特殊的 TS 类型: this 类型
类的成员方法可以直接返回一个 this, 这样就可以很方便的实现链式调用
class WorkFlow {
step1() {
return this;
}
step2() {
return this;
}
}
let workFlow = new WorkFlow();
workFlow.step1().step2();
复制代码
在继承的时候,this
也可以表现出多态(this 既可以是父类型,也可以是子类型)
class WorkFlow {
step1() {
return this;
}
step2() {
return this;
}
}
let workFlow = new WorkFlow();
workFlow.step1().step2();
class MyFlow extends WorkFlow {
next() {
return this;
}
}
let myflow = new MyFlow();
// myflow.next(): MyFlow {}
console.log("myflow.next(): ", myflow.next());
// myflow.next().step1(): MyFlow {}
console.log("myflow.next().step1(): ", myflow.next().step1().next().step2());
复制代码