Reputation: 15434
I am new to dart. In typescript I could do something like this:
// 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());
So business logic can explicitly define what it needs and then actual implementation of those dependencies can be done without interchanging any types (type files).
I something like this possible in dart? Or the only option is to define abstract class Repository
in business logic and then import this abstract class in repository file and make Repository class extend it?
Upvotes: 0
Views: 333
Reputation: 24671
JavaScript being a dynamically typed language and TypeScript merely being a development-level superset of that, TypeScript interfaces aren't (and can't be) hard contracts. They are merely a scaffold for normal JavaScript objects to conform to that throw compile-time (but not runtime) errors if they fail to adhere to the definition.
Dart, on the other hand, is a strongly-typed language, so interfaces are bound to class definitions instead of arbitrary objects and with iron-clad contracts. As such, you will need to explicitly define classes that implement the interfaces before you can use them.
// 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 {}
}
Here you define the interfaces as well as the BusinessLogic
class. Note that Dart just uses abstract classes for this purpose, so the convention is to start the class name with "I" to differentiate interfaces from base classes. Apart from that, the only other differences are largely syntactic.
// repo.dart
class Item implements IItem {
String item;
}
class Repository implements IRepository {
Future<void> addItem(IItem item) async {
/* impl */
}
}
Here the classes get defined that implement the interfaces. Once again, the differences here are largely syntactic with the exception that Item
must be explicitly defined and it must implement IItem
.
(One tangential thing to note is that, in your TypeScript code, your Repository
class doesn't actually reference the Repository
or Item
interface but instead defines a structure and an inline type restriction that just so happens to be compatible with them. While this wouldn't likely result in runtime bugs, these are typos that would need to be fixed if this were production code. Incidentally, if TypeScript were strongly-typed like Dart, this typo would be an error instead.)
// runtime.dart
import './business_logic' show BusinessLogic;
import './repo' show Repository;
final logic = BusinessLogic(Repository());
The only differences here are syntactic. Note that the show
syntax is merely to match the selective imports from the TypeScript and isn't actually necessary.
Upvotes: 2