我对飞镖很陌生。在打字稿中,我可以这样做:
// business-logic.ts
interface Item { name: string; }
interface Repository {
addItem: (item: Item) => Promise<void>;
}
export class BusinessLogic {
private repo: Repository;
constructor(repo: Repository) {
this.repo = repo;
}
async doSomething() {
await this.repo.addItem({ name: 'apple' });
}
}// repo.ts
export class Repository {
async addItem(item: { name: string }) { /* impl */ }
}// runtime.ts
import { BusinessLogic } from './business-logic';
import { Repository } from './repo';
const logic = new BusinessLogic(new Repo());因此,业务逻辑可以显式地定义它需要什么,然后可以在不交换任何类型(类型文件)的情况下完成这些依赖关系的实际实现。
我在飞镖里可能是这样的吗?或者唯一的选择是在业务逻辑中定义抽象类Repository,然后在存储库文件中导入这个抽象类并使repository类扩展它?
发布于 2021-01-28 20:45:51
JavaScript是一种动态类型的语言,而TypeScript仅仅是这种语言的开发级超集,TypeScript接口不是(也不可能)硬契约。它们只是普通JavaScript对象的脚手架,如果它们不遵守定义,那么它们就会符合抛出的编译时错误(而不是运行时错误)。
另一方面,Dart是一种强类型语言,因此接口被绑定到类定义,而不是任意对象和铁板一块的契约。因此,在使用接口之前,需要显式定义实现接口的类。
// business_logic.dart
abstract class IItem {
String item;
}
abstract class IRepository {
Future<void> addItem(IItem item);
}
class BusinessLogic {
Repository _repo;
BusinessLogic(this._repo);
void doSomething() async {}
}这里定义了接口以及BusinessLogic类。请注意,Dart只是为此使用抽象类,因此惯例是以"I“开头类名,以区分接口和基类。除此之外,唯一的其他区别主要是句法。
// repo.dart
class Item implements IItem {
String item;
}
class Repository implements IRepository {
Future<void> addItem(IItem item) async {
/* impl */
}
}这里定义了实现接口的类。同样,这里的区别主要是语法,除了必须显式定义Item并必须实现IItem这一例外。
(需要注意的一点是,在TypeScript代码中,Repository类实际上并不引用Repository或Item接口,而是定义了结构和内联类型限制,这些结构和限制恰好与它们兼容。虽然这不太可能导致运行时错误,但如果这是生产代码,则需要修复这些排版。顺便说一句,如果TypeScript是像Dart那样强类型的,那么这个错误将是一个错误。)
// runtime.dart
import './business_logic' show BusinessLogic;
import './repo' show Repository;
final logic = BusinessLogic(Repository());这里唯一的区别是句法。注意,show语法仅仅是为了匹配来自TypeScript的选择性导入,而实际上并不是必需的。
https://stackoverflow.com/questions/65942576
复制相似问题