一、为什么需要抽象类
有时,某个类只表示一个抽象概念,主要用于提取子类共有的成员,而不能直接创建它的对象。该类可以作为抽象类。
给类前面加上 abstract ,表示该类是一个抽象类,不可以创建一个抽象类。
二、抽象成员
父类中,可能知道有些成员是必须存在的,但是不知道该成员的值或实现是什么,因此,需要有一种强约束,让继承该类的子类,必须要实现该成员。
抽象类中,可以有抽象成员,这些抽象成员必须在子类中实现。
abstract class Chess {
x: number = 0;
y: number = 0;
abstract readonly name: string;
}
class Horse extends Chess {
readonly name: string = "马";
}
class Pao extends Chess {
readonly name: string;
constructor() {
super();
this.name = "炮";
}
}
class Soldier extends Chess {
get name() {
return "兵";
}
}
const h = new Horse()
const p = new Pao()
const s = new Soldier()
console.log(h.name, p.name, s.name); // 马 炮 兵
abstract class Chess {
x: number = 0;
y: number = 0;
abstract readonly name: string;
abstract move(targetX: number, targetY: number): boolean;
}
class Horse extends Chess {
readonly name: string = "马";
move(targetX: number, targetY: number): boolean {
this.x = targetX;
this.y = targetY;
console.log("马移动成功")
return true;
}
}
class Pao extends Chess {
move(targetX: number, targetY: number): boolean {
this.x = targetX;
this.y = targetY;
console.log("炮移动成功")
return true;
}
readonly name: string;
constructor() {
super();
this.name = "炮";
}
}
class Soldier extends Chess {
get name() {
return "兵";
}
move(targetX: number, targetY: number): boolean {
this.x = targetX;
this.y = targetY;
console.log("兵移动成功")
return true;
}
}
const h = new Horse()
const p = new Pao()
const s = new Soldier()
h.move(3, 5) // 马移动成功
p.move(2, 3) // 炮移动成功
s.move(1, 2) // 兵移动成功
三、设计模式
设计模式:面对一些常见的功能场景,有一些固定的、经过多年实践的成熟方法,这些方法称之为设计模式。
模板模式:有些方法,所有的子类实现的流程完全一致,只是流程中的某个步骤的具体实现不一致,可以将该方法提取到父类,在父类中完成整个流程的实现,遇到实现不一致的方法时,将该方法做成抽象方法。
abstract class Chess {
x: number = 0;
y: number = 0;
abstract readonly name: string;
move(targetX: number, targetY: number): boolean {
console.log("1.边界判断");
console.log("2.目标位置是否已有己方棋子");
// 3.棋子移动规则判断
if (this.rule(targetX, targetY)) {
this.x = targetX;
this.y = targetY;
console.log(`${this.name}移动成功`);
return true;
}
console.log(`${this.name}移动失败`);
return false
}
protected abstract rule(targetX: number, targetY: number):boolean
}
class Horse extends Chess {
readonly name: string = "马";
protected rule(targetX: number, targetY: number): boolean {
return true;
}
}
class Pao extends Chess {
readonly name: string;
protected rule(targetX: number, targetY: number): boolean {
return false;
}
constructor() {
super();
this.name = "炮";
}
}
class Soldier extends Chess {
protected rule(targetX: number, targetY: number): boolean {
return true;
}
get name() {
return "兵";
}
}
const h = new Horse()
const p = new Pao()
const s = new Soldier()
h.move(3, 5)
p.move(2, 3)
s.move(1, 2)
// 输出
// 1.边界判断
// 2.目标位置是否已有己方棋子
// 马移动成功
// 1.边界判断
// 2.目标位置是否已有己方棋子
// 炮移动失败
// 1.边界判断
// 2.目标位置是否已有己方棋子
// 兵移动成功