私のようないくつかの依存関係を持つ親サービスがあります
@Injectable()
export class ParentService{
constructor(private http:Http, private customService:CustomService){}
}
サービスを拡張したい
@Injectable()
export class ChildService extends ParentService{
constructor (){
super(??) <= TypeScript now asking to enter two parameters according to ParentServie's constructor
}
}
編集-----------------
@Injectable()
export class ParentService{
constructor(private http:Http, private customService:CustomService){}
get(){this.http.get(...)}
}
@Injectable()
export class ChildService extends ParentService{
constructor (private http:Http, private customService:CustomService){
super(http, customService)
}
}
次に、コンポーネントで使用できますか?
export class Cmp {
constructor(private childService:ChildService){
this.childService.get()
}
}
スーパークラスのパラメーターを繰り返し、スーパーコールに渡す必要があります。
@Injectable()
export class ChildService extends ParentService{
constructor (http:Http, customService:CustomService){
super(http, customService);
}
}
継承と依存関係の注入 のように回避するための「ハック」がいくつかあります
単に基本サービスを作成してください... non _@Injectable()
!たとえば、LoginService
でユーザープロファイルを取得するメソッドを提供する必要があります。このメソッドはLoginService
のインスタンスごとに異なり、親クラスはこのメソッドがどこから来たかについて何も知らない必要があります。ラムダにすることも、関数をエクスポートすることも、別のサービスのメソッドにすることもできます。これを実現するために、親サービスを宣言できます。
// Don't annotate it with @Injectable() ! It's a simple class.
export abstract class BaseLoginService {
constructor(
// This won't be injected automatically,
// child class must call super() and provide value for this argument.
// Note: it's private, can't be accessed outside of BaseLoginService class
private http: HttpClient,
// Method used to retrieve user profile
private profileGetter: () => Observable<UserDetails>,
private router: Router
) {
this.profileGetter().subscribe(); // Do something with this method
}
次に、子クラスで拡張します。
// Child class must be annotated with @Injectable(),
// if you don't need to extend it further
@Injectable()
export class LoginService extends BaseLoginService {
constructor(
// Note: no public/private/protected here - "http"
// will be just an argument
http: HttpClient,
private profileService: ProfileService, // This is the private field of LoginService class
router: Router,
// Some service used by LoginService class, parent class BaseLoginService
// doesn't need to know about SomeOtherService
private someOtherService: SomeOtherService
) {
super(
http,
// Need lambda here to capture profileService instance. If
// profileService.getUserDetailsMethod doesn't use instance
// fields or methods, then we can simply write
// "profileService.getUserDetailsMethod" (without quotes, obviously).
() => profileService.getUserDetailsMethod(),
router
);
this.someOtherService.doSomething(); // Custom initialization code
}
注:モジュールのproviders
セクションでは、親LoginService
の代わりにBaseLoginService
を指定します。
providers: [
LoginService,
コンポーネントクラスで使用します。
export class LoginComponent implements OnInit {
constructor(
private loginService: LoginService
) {
}
親サービスを使用する必要がある場合(たとえば、親サービスクラスの機能のみを必要とする共有コンポーネントで)、次のようにBaseLoginService
を指定します。
providers: [
{provide: BaseLoginService, useExisting: LoginService}, // For those components which need functionality from base class only
LoginService, // Still need this one for those components which need functionality from child class
抽象クラスprotected
でDIサービスを作成し、サブクラスでコンストラクターを省略すると、サービスはサブクラスで使用可能になります。