Spark323
Spark323

Reputation: 1585

Inheritance and Polymorphism with service and providers

I'm trying to learn Angular2 but have a bit of trouble. I have an abstract Service class called ParentService

export abstract class ParentService {

}

and another Service class that extends ParentService called ChildService

export class ChildService extends ParentService {

}

Then I have a component class called input.component

import { Component } from "@angular/core";

import { ParentService } from "./service/parent.service";

@Component({
    selector: 'app-input',
    templateUrl: './input.component.html'
})
export class InputComponent {
    constructor(private parentService: ParentService) {}

}

And in my app.component I provide an instance of the ChildService

import { Component } from '@angular/core';
import { ChildService } from './service/child.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [ChildService]
})
export class AppComponent {

}

However, this doesn't work. It builds fine, but when running the app I get an error:

EXCEPTION: Error in ./AppComponent class AppComponent - inline template:4:16 caused by: No provider for ParentService!

Is this possible to do? I just want the input.component to know a ParentService. I don't really want it to know the implementation.

Upvotes: 0

Views: 1416

Answers (2)

Alexander Leonov
Alexander Leonov

Reputation: 4794

It is possible but with a little addition.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [{provide: ParentService, useClass: ChildService}]
})
export class AppComponent {

}

The gotcha here is that DI in angular 2 will not try to infer any relations between classes. So, by default in order to inject ParentService you must provide ParentService, period. But luckily we can override this behavior with the construct above. It tells DI container literally "if someone asks for ParentService then create and give them an instance of ChildService instead".

Upvotes: 2

Harry Ninh
Harry Ninh

Reputation: 16758

You can't expect Angular2 to automatically wire up sub-classes to original class declaration like that. What if you have 2 sub-classes DogService and CatService that both inherit AnimalService declared in providers list, which one should be used?

Instead, you will need to specify it explicitly:

providers: [{provide: ParentService, useClass: ChildService}]

Documentation: https://angular.io/docs/ts/latest/guide/dependency-injection.html

Upvotes: 2

Related Questions