简体   繁体   中英

How does java get to know which implementation object of interface to return?

Please be gentle while answering, I am not a java developer (or developer in General)

While trying xml parsing with java I came across following -

NodeList nodelist = document.getElementsByTagName("item");

Herein xml dom object let me collect all objects depending on tag name I provide, but return type is an Interface called - nodelist. Since interface can not be instantiated it was a bit surprising for me.

Keeping break point and debugging the code I realized that I actually get object for class DeepNodeListImpl which implements NodeList interface.

How does this happen? How does java know to return object of "some implementation" held by my Interface "object" in the statement declared above.

One more thing - while reading the java api I found that IIOMetadataNode implements the NodeList but my previous code snippets does not get me object of type IIOMetadataNode

Excellent Question.

Java does not know which implementation of objects to return.

In your question, you reference the Document class and its getElementsByTagName method. Document is an interface which means that by itself it has no implementation code.

Thus whoever implements the Document interface gets to choose all the details (including which NodeList implementation to return from the getElementsByTagName method).

In the code for getElementByTagName there will be something like

NodeList nodeList = new DeepNodeListImpl();
// do something with nodeList
return nodeList;

Java "knows" to use this type because the code for that method will explicitly choose the implementation.

A method can always return a subclass of what it promises to return and in general any value can at runtime be a subtype of the type it is declared as.

The implementor of getElementsByTagName is therefore free to return something of type DeepNodeListImpl as long as it is a subtype of NodeList .

That's a feature of object oriented programming. A class can extend a base class (or implement an interface). The base class or the implemented interface can then be used as a "common denominator". That means: A method that returns an object of some type may actually return an object of any class derived from that type.

That's what happening in your case. You also do not really need about the actual class being used - you can use any method provided by the interface.

And you shouldn't make any assumptions about the type being returned other than the interface type. Only if you're 100% absolutely sure you may cast to the specialized type. Example: if you did a cast to DeepNodeListImpl now, but the implementation of the XML parser was changed, you might get an exception during the cast if the implementation does not return a DeepNodeListImpl or one of the derived classes anymore.

Here's a real life analogy. Suppose you contract a company to send you a gardener.

What you expect to get is a gardener who can mow your lawn and trim the hedges (the gardener interface).

What you get is a real person, who might be a man, woman, old or young and who might be able to do non-gardening related things like prepare dinner (implements the cook interface), but can at least mow your lawn and trim the hedges (implements the gardener interface).

The company is responsible for determining which implementation you get (the company plays the role of an 'abstract factory').

Normally you don't care about the non-gardening related things this implementation can do.

However, if you know your gardener can cook and you want your gardener to prepare your dinner then you need to cast the gardener to cook:

Gardener gardener = AbstractFactory.getGardener();
gardener.mowLawn();
// cast 
Cook cook = (Cook) gardener;
cook.prepareDinner();

Note that this circumvents the abstraction (and thus information-hiding) offered by the AbstractFactory: you asked for a gardener and were not supposed to care about other skills. The result of this is that if you start using a different factory in future you might get a gardener who cannot cook, and your cast will cause a ClassCastException at runtime (your dinner might taste horrible).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM