Подтвердить что ты не робот

Связывание класса с интерфейсом

Используя typescript, я могу легко привязать классы к себе:

bootstrap(MyAppComponent, [MyClass]);

Однако я хотел бы привязать свой класс к интерфейсу, например:

boostrap(MyAppComponent, [???]);

чтобы я мог впрыснуть его следующим образом:

class MyAppComponent {
    constructor(my_class : IMyClass){
    }
};

Возможно ли это в Angular2? Если да, то как мне нужно указать привязку?

4b9b3361

Ответ 1

Короче говоря, проблема заключается в том, что интерфейсы исчезают при компиляции typescript. Поэтому вам придется использовать @Inject со строкой.

Или там другой вариант, если вы проверите последнюю статью Виктора Савкина, вы можете найти это в комментариях:

Некоторые предпосылки. В TypeScript интерфейсы являются структурными и не сохраняются во время выполнения. Таким образом, вы должны использовать ILoginService следующим образом:

constructor(@Inject("ILoginService") s:ILoginService).

Вам не нужно использовать строку - любой объект может быть передан там. Мы фактически предоставляем объект под названием OpaqueToken, который может быть использован для этой цели.

interface ILoginService { login(credentials);}
const ILoginService = new OpaqueToken("LoginService");

можно использовать следующим образом:

constructor(@Inject(ILoginService) s:ILoginService).

Ответ 2

Я не знаю, возможно ли с интерфейсом, поскольку интерфейс не будет доступен во время выполнения (javascript не знает об интерфейсе). Но это можно сделать с помощью абстрактных классов.

//абстрактный-родитель-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";
  }
}

//ЦМФ-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());
    }
}

//ЦМФ-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());
    }
}

Но проблема с этой реализацией - HibernateService и Теперь JDBCService не может расширить какой-либо другой класс, поскольку они уже поженились с 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");
    }
}

Если вы используете этот шаблон для DI, убедитесь, что ваши дочерние классы не будут расширяться в будущем.