2015-08-27 18 views
22

Sử dụng nguyên cảo, tôi có thể dễ dàng liên kết các lớp học cho riêng mình:Ràng buộc một lớp học để một giao diện

bootstrap(MyAppComponent, [MyClass]); 

Tuy nhiên, tôi muốn để ràng buộc lớp học của tôi để một giao diện, như ví dụ:

boostrap(MyAppComponent, [???]); 

sao cho tôi có thể tiêm nó như sau:

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

Điều này có khả thi trong Angular2 không? Nếu có, làm thế nào để tôi phải xác định ràng buộc?

Trả lời

24

Để làm cho nó ngắn vấn đề là giao diện biến mất khi bản ghi được biên soạn. Vì vậy, bạn phải sử dụng @Inject với một chuỗi.

Hoặc có lựa chọn khác, nếu bạn kiểm tra the last article of Victor Savkin bạn có thể tìm thấy điều này trong các ý kiến:

Một số nền. Trong TypeScript, các giao diện là cấu trúc và không được giữ lại trong thời gian chạy. Vì vậy, bạn phải sử dụng ILoginService như sau:

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

Bạn không cần phải sử dụng một chuỗi - bất kỳ đối tượng có thể được thông qua trong đó. Chúng tôi thực sự cung cấp một đối tượng được gọi là OpaqueToken có thể được sử dụng cho mục đích này.

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

thể được sử dụng như thế này:

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

lý do tại sao 'mới OpaqueToken ("LoginService") 'nhận được thông qua' LoginService' và không phải 'ILoginService'? –

6

Tôi không biết nếu nó là có thể với giao diện như giao diện sẽ không có sẵn tại thời gian chạy (javascript không biết về giao diện). Nhưng nó có thể được thực hiện bằng cách sử dụng các lớp trừu tượng.

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

Nhưng vấn đề với việc thực hiện này là HibernateService và JDBCService không thể mở rộng bất kỳ lớp khác bây giờ bởi vì họ đã kết hôn với 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"); 
    } 
} 

Nếu bạn đang sử dụng mô hình này cho DI, làm cho nó chắc chắn rằng các dịch vụ lớp con của bạn sẽ không mở rộng bất kỳ chức năng khác trong tương lai.

Các vấn đề liên quan