Java polymorphism via runtime injection
I've heard that in Java I can achieve polymorphism through runtime injection. Can someone please show a simple example of how this is done? I search the web, but I can't find anything: maybe I was looking wrong. So I am aware of polymorphism via interface and extension like
class MyClass extends Parent implements Naming
in this case I achieve polymorphism twice: MyClass is of type Parent
and at the same time Naming
. But I don't understand how injection works. The idea is that I would not use the keyword @Override
during injection. Hope this question is clear. Thank.
So the end result here, in my understanding, is to change the behavior of the method through injection, not @Override
at design time.
source to share
So, I know about polymorphism via interface and extension, like
class MyClass extends Parent implements Naming
This is known as heredity, not polymorphism. MyClass
is Parent
as well MyClass
as is Naming
. This inheritance
allows you to achieve polymorphism
.
Consider a class other than MyClass
that also implements Naming
:
class SomeOtherClass implements Naming {
@Override
public void someMethodDefinedInTheInterface() {
}
}
Now, consider a method that takes an argument Naming
somewhere in your codebase:
public void doSomething(Naming naming) {
naming.someMethodDefinedInTheInterface();
}
The method doSomething
can be passed an instance of any class
that implements Naming
. Thus, both of the following calls are in effect:
doSomething(new MyClass());//1
doSomething(new SomeOtherClass());//2
Note how you can call doSomething
with different parameters. At run time, the first call will call someMethodDefinedInTheInterface
from MyClass
, and the second call will call someMethodDefinedInTheInterface
from SomeOtherClass
. This is called runtime-polymorphism
, which can be achieved through inheritance.
But I don't understand how injection works. The idea is that I would not use the @Override keyword during injection
This is true in a broader sense. For inject
something to be in class, the class must ideally support composition
over inheritance
. See this answer, which does a good job of explaining why composition is preferred over inheritance.
To expand on the above example from my answer, change the method doSomething
as follows:
public class ClassHasANaming {
private Naming naming;
public ClassHasANaming(Naming naming) {
this.naming = naming;
}
public void doSomething() {
naming.someMethodDefinedInTheInterface();
}
}
Observe how it now ClassHasANaming
has a dependency Naming
that can be injected from the outside world:
ClassHasANaming callMyClass = new ClassHasANaming(new MyClass());
callMyClass.doSomething();
If you are using the Factory pattern , you can actually choose which subclass will be created at startup.
Do you think we could do what we did above using inheritance
?
public class ClassIsANaming implements Naming {
public void doSomething() {
someMethodDefinedInTheInterface();
}
@Override
public void someMethodDefinedInTheInterface() {
//....
}
}
The answer is no . ClassIsANaming
tied to one implementation of the method someMethodDefinedInTheInterface
at compile time. `
source to share
Taking a contrived example. You have a class Store
that stores things:
class Store {
private List l
void store(Object o) {
l.add(o);
}
void setStoreProvider(List l) {
this.l = l
}
}
You can enter the actual List
used as the backup storage using setStoreProvider
which can be a linked list, an array with a backup list, etc.
Hence, depending on the injected type, your class Store
will have properties of the injected type (regarding memory usage, speed, etc.).
It's kind of polymorphism without a class implementing the interface.
source to share