Using typescript, I can easily bind classes to themselves:
bootstrap(MyAppComponent, [MyClass]);
However, I would like to bind my class to an interface, like such:
boostrap(MyAppComponent, [???]);
such that I can inject it as follows:
class MyAppComponent {
constructor(my_class : IMyClass){
}
};
Is this possible in Angular2? If yes, how to I have to specify the binding?
You can bind the agent to specific interfaces on a host machine. This can be useful in situations where security is of high concern. For example, many enterprise networks use a gateway to separate the internal network from the Internet.
Interfaces are useful for the following: Capturing similarities among unrelated classes without artificially forcing a class relationship. Declaring methods that one or more classes are expected to implement. Revealing an object's programming interface without revealing its class.
Interfaces are used in Java to achieve abstraction. By using the implements keyword, a java class can implement an interface. In general terms, an interface can be defined as a container that stores the signatures of the methods to be implemented in the code segment. It improves the levels of Abstraction.
To make it short the problem is that Interfaces disappear when typescript is compiled. So you'd have to use @Inject with a string.
Or there's another option, if you check the last article of Victor Savkin you can find this in the comments :
Some background. In TypeScript, interfaces are structural and are not retained at runtime. So you have to use ILoginService as follows:
constructor(@Inject("ILoginService") s:ILoginService).
You don't have to use a string - any object can be passed in there. We actually provide an object called OpaqueToken that can be used for this purpose.
interface ILoginService { login(credentials);}
const ILoginService = new OpaqueToken("LoginService");
can be used like this:
constructor(@Inject(ILoginService) s:ILoginService).
I dont know if it is possible with interface as interface will not be available at runtime (javascript does not know about interface). But it can be done using abstract classes.
//abstract-parent-service.ts
export class DatabaseService{
getService: ()=>string;
}
//hibernate.service.ts
import {DatabaseService} from "./abstract-parent-service";
export class HibernateService implements DatabaseService{
constructor() { }
getService() {
return "i am hibernate";
}
}
//jdbc.service.ts
import {DatabaseService} from "./abstract-parent-service";
export class JDBCService implements DatabaseService{
constructor() { }
getService() {
return "i am Jdbc";
}
}
//cmp-a.component.ts
import {DatabaseService} from "./abstract-parent-service";
import {HibernateService} from "./hibernate.service";
@Component({
selector: 'cmp-a',
template: `<h1>Hello Hibernate</h1>`,
providers: [{provide: DatabaseService, useClass: HibernateService}]
})
export class CmpAComponent {
constructor (private databaseService: DatabaseService) {
console.log("Database implementation in CompA :"+this.databaseService.getService());
}
}
//cmp-b.component.ts
import {DatabaseService} from "./abstract-parent-service";
import {HibernateService} from "./hibernate.service";
@Component({
selector: 'cmp-b',
template: `<h1>Hello Jdbc</h1>`,
providers: [{provide: DatabaseService, useClass: JDBCService}]
})
export class CmpAComponent {
constructor (private databaseService: DatabaseService) {
console.log("Database implementation in CompA :"+this.databaseService.getService());
}
}
But the problem with this implementation is HibernateService and JDBCService are not able to extend any other class now because they have already got married with DatabaseService.
class A{
constructor(){
console.log("in A");
}
}
class B extends A{
constructor(){
super();
console.log("in B");
}
}
class C extends A{
constructor(){
super();
console.log("in C");
}
}
let c = new C();
//This thing is not possible in typescript
class D extends B, C{//error: Classes can only extend a single class
constructor(){
super();// which constructor B or C
console.log("in D");
}
}
If you are using this pattern for DI, make it sure that your child class services are not going to extend any other functionality in future.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With