The dependency Inversion principle says that (Head First Java):
What does it mean with respect to inheritance? As a subclass depends on concrete class.
I am asking for a case when say - There is an interface Bird
(doesn't have fly method as some birds cant fly), which represents all Non-Flying Birds. So I create a class - NonFlyingBird
which implements Bird
.
Now I want to make a class for Birds that can fly. As NonFlyingBirds
and FlyingBirds
have the same attributes I extend the FlyingBirds
from NonFlyingBirds
and Implement Flyable
to give it flying behavior.
Do Doesn't it break the dependency Inversion principle as FlyingBirds
is extending from a concrete class NonFlyingBirds
?
interface Bird { // Represents non Flying birds
void getColor();
void getHeight();
...
}
class NonFlyingBird implements Bird {
void getColor();
void getHeight();
...
}
class FlyingBird extends NonFlyingBird implements Flyable { // Does it break Dependency Inversion principle by extending concrete NonFlyingBird class?
Flyable fly;
...
}
Note - The only reason I am extending is because the FlyingBird
has the same attributes and methods as NonFlyingBird
+ the flying behaviour. So it kind of makes sense to reuse code by inheritance.
Despite I liked an example with strategy from answers there, I will answer too, because I think you are confused a bit about dependency inversion principle.
Don't use this, if you don't really need LinkedList behaviour:
public class A {
private LinkedList<SomeClass> list;
//...
}
Use that instead:
public class A {
private List<SomeClass> list; //or even use Collection or Iterable
//...
}
Dependencies are what we use inside our class.
Inheritance is what we call IS-A relationship and it has nothing to do with the principle. If you want to make class A that inherits class B, you need to answer a question: is it true that A is B. If you ask this question, you'll find that expression "FlyingBird
is a NonFlyingBird
" is a noncense.
Think about this: not all birds can fly and not only birds(e.g. flies) can fly.
It may lead us to an idea that we should create interface Flyable as you already done. Then we should rename NonFlyingBird
to just SimpleBird
, because if some creature is a bird it doesn't mean it can fly. In the end you will get:
class FlyingBird extends SimpleBird implements Flyable {
void fly() {
...
}
...
}
Hope it'll help.