与其他一些 OO 语言一样,在 typescript 中也不可能有多重继承,但可以实现多个接口,这是接口适用的一种用例。
另一个原因是,如果您想将不同的实现分布在不同的命名空间/模块中,但又希望它们都实现一组特定的方法:
namespace callbacks {
export interface Callback<T> {
getName(): string;
execute(): T;
}
}
namespace mynamespace1 {
export class Callback implements callbacks.Callback<string> {
public getName(): string {
return "mynamespace1.Callback";
}
public execute(): string {
return "executed";
}
}
}
namespace mynamespace2 {
export class Callback implements callbacks.Callback<boolean> {
public getName(): string {
return "mynamespace2.Callback";
}
public execute(): boolean {
return true;
}
}
}
但最好的理由(在我看来)是它允许您将实现类隐藏在一个闭包中,这样就没有人可以直接创建它们,只能通过工厂函数或某些操作:
namespace logging {
const httpLoggingEndpoint: URL = new URL(...);
const fileLoggingFilePath: string = "LOG_FILE_PATH";
export enum LoggerType {
Console,
Http,
File
}
export interface Logger {
log(message: string): void;
}
export function getLogger(type: LoggerType): Logger {
switch (type) {
case LoggerType.Console:
return new ConsoleLogger();
case LoggerType.Http:
return new HttpLogger();
case LoggerType.File:
return new FileLogger();
}
}
class ConsoleLogger implements Logger {
public log(message: string): void {
console.log(message);
}
}
class HttpLogger implements Logger {
public log(message: string): void {
// make a request to httpLogingEndpoint
}
}
class FileLogger implements Logger {
public log(message: string): void {
// log message to the file in fileLoggingFilePath
}
}
}
这种方式没有人可以直接实例化记录器,因为没有导出任何实际的类。
关于这个主题的另一点是,在打字稿中,类可以被视为接口:
class Logger {
public log(message: string) {
console.log(message);
}
}
class HttpLogger implements Logger {
public log(message: string) {
// log using an http request
}
}
例如用于mixins,因此实际上我的前两个场景也可以使用类来完成,尽管我的最后一个示例不适用于类,因为这样您就可以实例化基类并通过这样做绕过了不能直接调用不同构造函数的“安全机制”。