Oop 如何模拟抽象类并调用其构造函数?
我正试图通过用TypeScript编写代码来遵循一本C#design patterns的书。也许这是我的第一个错误,但这是我喜欢学习语言的一种方式 TypeScript不支持类的抽象关键字,所以我尝试模拟它。也许这是我的第二个错误 以下是我的界面和类:Oop 如何模拟抽象类并调用其构造函数?,oop,design-patterns,typescript,Oop,Design Patterns,Typescript,我正试图通过用TypeScript编写代码来遵循一本C#design patterns的书。也许这是我的第一个错误,但这是我喜欢学习语言的一种方式 TypeScript不支持类的抽象关键字,所以我尝试模拟它。也许这是我的第二个错误 以下是我的界面和类: interface IEngine { getSize(): number; getTurbo(): boolean; } class AbstractEngine implements IEngine { constructor(
interface IEngine {
getSize(): number;
getTurbo(): boolean;
}
class AbstractEngine implements IEngine {
constructor(private size: number, private turbo: boolean) {
throw "Abstract class";
}
public getSize(): number {
return this.size;
}
public getTurbo(): boolean {
return this.turbo;
}
public toString(): string {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec(this.constructor.toString());
var className = (results && results.length > 1) ? results[1] : '';
return className + " (" + this.size + ")";
}
}
class StandardEngine extends AbstractEngine {
constructor(size: number) {
// not turbo charged
super(size, false);
}
}
当尝试用新的AbstractEngine(1,true)
实例化AbstractEngine时,我得到了预期的“抽象类”错误
当尝试用新标准引擎(9000)
实例化标准引擎时,我还得到一个“抽象类”错误
有没有一种方法可以在TypeScript中模拟一个抽象类,让它无法实例化,但仍然在一个扩展它的类中调用super?模拟抽象方法怎么样,我可以保护这些方法并仍然调用super方法吗?当调用
标准引擎构造函数时,您可以调用super(size,false)
。对基类的调用是生成第二个“抽象类”错误的原因
要模拟实例化时将抛出的抽象基类,请创建从派生类调用的Init函数
class AbstractEngine implements IEngine {
private _size: number;
private _turbo: boolean;
constructor() {
throw "Abstract class";
}
init(size:number, turbo: boolean) {
this._size = size;
this._turbo = turbo;
}
}
class StandardEngine extends AbstractEngine {
constructor(size: number) {
// not turbo charged
// do not call super here
init(size, false);
}
}
另一种解决方案是使用一个属性,如果set指示正在从子类调用构造函数,则可以安全地继续。如下所示:
class AbstractEngine {
safe; // IMPORTANT : do not initialize
constructor(private size: number, private turbo: boolean) {
if(!this.safe) throw "Abstract class"; // IMPORTANT
}
}
class StandardEngine extends AbstractEngine {
constructor(size: number) {
this.safe = true; // IMPORTANT
super(size, false);
}
}
我劝你不要那样做。当TypeScript编译器将实现抽象函数的机制时,是时候使用它了。但是在运行时起作用的黑客是不可理解的,并且会降低性能
界面是TypeScript的强大功能。它们应该被大量使用
你的例子应该这样写:
interface Engine {
getSize(): number;
getTurbo(): boolean;
}
class StandardEngine implements Engine {
constructor(private size: number, private turbo: boolean) {
}
public getSize(): number {
return this.size;
}
public getTurbo(): boolean {
return this.turbo;
}
}
最简单的解决方案往往是最好的
如果您想在没有父类的情况下重用代码,那么就必须使用。混血是一种应对来自几个不同实体的技能的方法
或者,使用模块,可以保持私有实现(并因此根据需要组织它),并且只导出接口和工厂。例如:
module MyEngineModule {
export interface Engine {
getSize(): number;
getTurbo(): boolean;
}
export interface StandardEngine extends Engine {
}
export function makeStandardEngine(size: number, turbo: boolean): StandardEngine {
return new ImplStandardEngine(size, turbo);
}
// here classes are private and can inherit or use mixins…
class ImplEngine {
constructor(private size: number, private turbo: boolean) {
}
public getSize(): number {
return this.size;
}
public getTurbo(): boolean {
return this.turbo;
}
}
class ImplStandardEngine extends ImplEngine implements StandardEngine {
}
}
console.log(MyEngineModule.makeStandardEngine(123, true).getSize());
从今天起,已支持摘要
关键字
abstract class A {
foo(): number { return this.bar(); }
abstract bar(): number;
}
var a = new A(); // error, Cannot create an instance of the abstract class 'A'
class B extends A {
bar() { return 1; }
}
var b = new b(); // success, all abstracts are defined
但我需要能够在AbstractEngine中跨几个不同的具体类共享实现,而不仅仅是StandardEngine。很抱歉,我没有在我的帖子里说得那么明显。我看不出您的解决方案如何帮助实现这一点。编辑啊,没关系,我看到你提到了关于mixin的部分,这将实现跨多个具体类共享代码。我必须试一试。在使用mixin实现了这一点之后,我有点失望,因为我不得不将大量代码复制到StandardEngine和TurboEngine类。我希望有一个关键字能够解决这个问题,并消除调用applyMixins或抽象类或两者的必要性。此外,引擎上的自定义toString方法在实现为mixin时总是为类名打印“Engine”,而不是像使用继承时那样的“StandardEngine”或“TurboEngine”。我同意,混血儿缺乏优雅。它们是原型中的手动操作,而且不干燥。我建议您使用最后一种解决方案。在模块中,使用继承创建私有类。例如,ImplEngine← 安装标准发动机。从模块外部,ImplEngine将不会实例化。如果我在StandardEngine中忽略对super的调用,则会出现错误“派生类的构造函数必须包含“super”调用”。在尝试您的代码时,我还收到错误“找不到符号'init'”,因为它缺少“this”限定符。当我尝试此代码时,在实例化StandardEngine时,我仍然收到针对抽象类抛出的错误。我理解这个想法,但实现似乎不起作用。@Bryce,我纠正了错误。基类不应设置该值,否则子值将被覆盖:)