mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-23 06:10:02 +08:00
70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
// Dynamic dispatch: overridden methods called through base-typed
|
|
// references run the DERIVED implementation (the classic shapes example),
|
|
// while never-overridden methods stay correct through any static type.
|
|
class Shape {
|
|
label: string;
|
|
constructor(label: string) {
|
|
this.label = label;
|
|
}
|
|
area(): number {
|
|
return 0;
|
|
}
|
|
name(): string {
|
|
return this.label; // never overridden anywhere: devirtualized
|
|
}
|
|
report(): string {
|
|
// A base-class method calling a virtual one on its own `this` still
|
|
// dispatches on the dynamic class.
|
|
return `${this.name()}: ${this.area()}`;
|
|
}
|
|
}
|
|
class Circle extends Shape {
|
|
r: number;
|
|
constructor(r: number) {
|
|
super("circle");
|
|
this.r = r;
|
|
}
|
|
area(): number {
|
|
return 3 * this.r * this.r;
|
|
}
|
|
}
|
|
class Square extends Shape {
|
|
side: number;
|
|
constructor(side: number) {
|
|
super("square");
|
|
this.side = side;
|
|
}
|
|
area(): number {
|
|
return this.side * this.side;
|
|
}
|
|
}
|
|
class DoubleSquare extends Square {
|
|
constructor(side: number) {
|
|
super(side);
|
|
this.label = "double-square";
|
|
}
|
|
area(): number {
|
|
return 2 * super.area(); // super.method(): the BASE implementation
|
|
}
|
|
}
|
|
|
|
const c = new Circle(2);
|
|
const s = new Square(3);
|
|
const ds = new DoubleSquare(3);
|
|
console.log(c.area(), s.area(), ds.area());
|
|
|
|
function measure(sh: Shape): number {
|
|
return sh.area(); // virtual through the base type
|
|
}
|
|
console.log(measure(c), measure(s), measure(ds));
|
|
console.log(c.report(), s.report(), ds.report());
|
|
|
|
// Leaf-typed receivers of an overridden method are still exact.
|
|
const viaSquare: Square = ds;
|
|
console.log(viaSquare.area(), viaSquare.name());
|
|
|
|
// Reference identity survives widening: base === derived on the same object.
|
|
const wide: Shape = ds;
|
|
const other: Shape = c;
|
|
console.log(wide === ds, wide === s, other !== s);
|