打字稿抽象方法重载
Typescript abstract method overloading
我想在抽象 class 中重载抽象方法,如下所示:
abstract class Animal {
public abstract communicate(sentence: string): void;
public abstract communicate(notes: string[]): void;
}
class Human extends Animal {
public communicate(sentence: string): void {
// Do stuff
}
}
class Bird extends Animal {
public communicate(notes: string[]): void {
// Do stuff
}
}
然而,Typescript 给出了一个错误,指出我错误地扩展了基础 class(动物)
我做错了什么吗?就像期望根据 OOP 无论如何都会起作用的东西一样?还是 Typescript 不支持?
注意:参数的类型可以是完全不同的类型,与此示例不同。
那个抽象 class 期望实现两个方法签名。这两个方法签名是:
public abstract communicate(sentence: string): void;
public abstract communicate(notes: string[]): void;
它们可以这样实现:
class Human extends Animal {
communicate(sentence: string); // optional overload signature
communicate(notes: string[]); // optional overload signature
communicate(sentenceOrNotes: string | string[]) {
// Do stuff
}
}
最后的签名是实现签名。它需要与需要实现的方法签名兼容。
注意 Child 类
Child classes 需要与底座兼容,以便当您这样做时...
const animal: Animal = new Bird();
...child class 应该能够处理这两个调用:
animal.communicate("some sentence");
animal.communicate(["notes", "more notes"]);
在这种情况下,根据通信形式创建单独的接口可能更合适(或使用mixins):
interface CommunicatesWithSentences {
communicate(sentence: string);
}
class Human extends Animal implements CommunicatesWithSentences {
communicate(sentence: string) {
// Do stuff
}
}
就像@DavidSherret 所说的那样,sub-class 必须实现所有抽象 class 重载,而不仅仅是其中之一。所以你将无法真正使用抽象 class 重载来做你想做的事。
由于您想要 Bird
和 Human
具有不同的 communicate()
参数类型,由编译器强制执行,因此我将使用具有类型约束的泛型类型参数:
abstract class Animal<C extends string | string[]> {
public abstract communicate(communication: C): void;
}
class Human extends Animal<string> {
public communicate(sentence: string): void { }
}
class Bird extends Animal<string[]> {
public communicate(notes: string[]): void { }
}
class Bynar extends Animal<boolean> { // Error: 'boolean' does not satisfy the constraint 'string | string[]'.
public communicate(bit: boolean): void { }
}
const human = new Human();
human.communicate("hello"); // OK
human.communicate(["hello"]); // Error
const bird = new Bird();
bird.communicate("hello"); // Error
bird.communicate(["hello"]); // OK
提示:您也可以在这里使用 TS 2.3 default type arguments。
这样就可以了,希望对大家有用
export abstract class BaseComponent {
constructor(protected valueName: string) {
}
protected doSomethingMoreButOptional(config: IConfig): void { }
protected doSomething() {
if (valueName === 'derived') {
this.doSomethingMoreButOptional(new Config());
}
}
}
export class DerivedComponent extends BaseComponent {
private _xxx: any[];
private _yyy: any[];
constructor() {
super('derived');
super.doSomething();
}
protected doSomethingMoreButOptional(config: IConfig): void {
switch (config.ABC) {
case 'xxx':
config.options = this._xxx;
break;
case 'yyy':
config.options = this._yyy;
break;
default:
return;
}
}
}
我想在抽象 class 中重载抽象方法,如下所示:
abstract class Animal {
public abstract communicate(sentence: string): void;
public abstract communicate(notes: string[]): void;
}
class Human extends Animal {
public communicate(sentence: string): void {
// Do stuff
}
}
class Bird extends Animal {
public communicate(notes: string[]): void {
// Do stuff
}
}
然而,Typescript 给出了一个错误,指出我错误地扩展了基础 class(动物)
我做错了什么吗?就像期望根据 OOP 无论如何都会起作用的东西一样?还是 Typescript 不支持?
注意:参数的类型可以是完全不同的类型,与此示例不同。
那个抽象 class 期望实现两个方法签名。这两个方法签名是:
public abstract communicate(sentence: string): void;
public abstract communicate(notes: string[]): void;
它们可以这样实现:
class Human extends Animal {
communicate(sentence: string); // optional overload signature
communicate(notes: string[]); // optional overload signature
communicate(sentenceOrNotes: string | string[]) {
// Do stuff
}
}
最后的签名是实现签名。它需要与需要实现的方法签名兼容。
注意 Child 类
Child classes 需要与底座兼容,以便当您这样做时...
const animal: Animal = new Bird();
...child class 应该能够处理这两个调用:
animal.communicate("some sentence");
animal.communicate(["notes", "more notes"]);
在这种情况下,根据通信形式创建单独的接口可能更合适(或使用mixins):
interface CommunicatesWithSentences {
communicate(sentence: string);
}
class Human extends Animal implements CommunicatesWithSentences {
communicate(sentence: string) {
// Do stuff
}
}
就像@DavidSherret 所说的那样,sub-class 必须实现所有抽象 class 重载,而不仅仅是其中之一。所以你将无法真正使用抽象 class 重载来做你想做的事。
由于您想要 Bird
和 Human
具有不同的 communicate()
参数类型,由编译器强制执行,因此我将使用具有类型约束的泛型类型参数:
abstract class Animal<C extends string | string[]> {
public abstract communicate(communication: C): void;
}
class Human extends Animal<string> {
public communicate(sentence: string): void { }
}
class Bird extends Animal<string[]> {
public communicate(notes: string[]): void { }
}
class Bynar extends Animal<boolean> { // Error: 'boolean' does not satisfy the constraint 'string | string[]'.
public communicate(bit: boolean): void { }
}
const human = new Human();
human.communicate("hello"); // OK
human.communicate(["hello"]); // Error
const bird = new Bird();
bird.communicate("hello"); // Error
bird.communicate(["hello"]); // OK
提示:您也可以在这里使用 TS 2.3 default type arguments。
这样就可以了,希望对大家有用
export abstract class BaseComponent {
constructor(protected valueName: string) {
}
protected doSomethingMoreButOptional(config: IConfig): void { }
protected doSomething() {
if (valueName === 'derived') {
this.doSomethingMoreButOptional(new Config());
}
}
}
export class DerivedComponent extends BaseComponent {
private _xxx: any[];
private _yyy: any[];
constructor() {
super('derived');
super.doSomething();
}
protected doSomethingMoreButOptional(config: IConfig): void {
switch (config.ABC) {
case 'xxx':
config.options = this._xxx;
break;
case 'yyy':
config.options = this._yyy;
break;
default:
return;
}
}
}