I have a parent service which has some dependencies like
@Injectable()
export class ParentService{
constructor(private http:Http, private customService:Cus
If you make the DI services in the abstract class protected
and omit the constructor in the subclass, then the services are available in the subclass.
The parameters of the super class need to be repeated and passed to the super call:
@Injectable()
export class ChildService extends ParentService{
constructor (http:Http, customService:CustomService){
super(http, customService);
}
}
There are some "hacks" to work around like Inheritance and dependency injection
Simply make base service... non-@Injectable()
! For example, you need to supply a method to retrieve user profile in LoginService
. This method will be different for different instances of LoginService
, and parent class must not know anything about where from this method came: it can be lambda, it can be exported function, it can be a method of another service. To achieve this, you can declare parent service which
Parent service:
// 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
}
Then extend it in child class:
// 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
}
Note: in providers
section of module specify LoginService
instead of parent BaseLoginService
:
providers: [
LoginService,
and use it in component classes:
export class LoginComponent implements OnInit {
constructor(
private loginService: LoginService
) {
}
If you need to use parent service (e.g. in shared components which only need functionality from parent service class), then provide BaseLoginService
this way:
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