问题 如何在角度2中扩展具有依赖性的服务


我有一个父服务,有一些依赖,如

@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()
  }
}

3975
2017-08-29 14:12


起源



答案:


超类的参数需要重复并传递给超级调用:

@Injectable()
export class ChildService extends ParentService{
  constructor (http:Http, customService:CustomService){
    super(http, customService);
  }
}

有一些“黑客”可以解决 继承和依赖注入


12
2017-08-29 14:15



我调整了代码,它会起作用吗? - Han Che
不,构造函数错过了参数。 Angular2 DI从构造函数参数中读取它必须传递给组件的依赖项。 ChildService 不会传递任何内容,因为它没有构造函数参数。 super(http, customService) 是无效的,因为 http 和 customService 在子类中不知道。 - Günter Zöchbauer
抱歉忘记将参数添加到子组件构造函数中。不对吗? - Han Che
这应该工作。它与我在答案中显示的相似,但现在也有被覆盖的字段 http 和 customService 在里面 ChildService 同样。 - Günter Zöchbauer
嘿,如何超速跳绳 private 关键字in ChildService 构造函数? super() 应将它们存储为属性 - Tomas


答案:


超类的参数需要重复并传递给超级调用:

@Injectable()
export class ChildService extends ParentService{
  constructor (http:Http, customService:CustomService){
    super(http, customService);
  }
}

有一些“黑客”可以解决 继承和依赖注入


12
2017-08-29 14:15



我调整了代码,它会起作用吗? - Han Che
不,构造函数错过了参数。 Angular2 DI从构造函数参数中读取它必须传递给组件的依赖项。 ChildService 不会传递任何内容,因为它没有构造函数参数。 super(http, customService) 是无效的,因为 http 和 customService 在子类中不知道。 - Günter Zöchbauer
抱歉忘记将参数添加到子组件构造函数中。不对吗? - Han Che
这应该工作。它与我在答案中显示的相似,但现在也有被覆盖的字段 http 和 customService 在里面 ChildService 同样。 - Günter Zöchbauer
嘿,如何超速跳绳 private 关键字in ChildService 构造函数? super() 应将它们存储为属性 - Tomas


只需提供基本服务......@Injectable()!例如,您需要提供一种方法来检索用户配置文件 LoginService。对于不同的实例,此方法将有所不同 LoginService,和父类一定不知道从这个方法来到哪里:它可以是lambda,它可以是导出函数,它可以是另一个服务的方法。为此,您可以声明父服务 家长服务:

// 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

2
2018-05-12 17:27



这个答案应该得到更多的选票,谢谢! - Qualaelay