Java For loop and polymorphism - java

I was wondering how I could handle polymorphism in a for loop without using of "instanceof" like in C#.
Here is what I have :
An abstract class A :
public abstract class A
{
public abstract Map<Long, ? extends A> getNodes();
public abstract void setNodes(Map<Long, ? extends A> n);
}
B and C classes which extends A and implements abstract methods of A :
public class B
{
private Map<Long, C> childNodesC;
#Override
public Map<Long, ? extends A> getNodes()
{
return childNodesC;
}
#Override
public void setNodes(Map<Long, ? extends A> n)
{
for(C child : n)
childNodesC.put(child.getId(), child);
}
}
Is a for-loop like this one in setNodes() method, possible in Java ? I mean, is there a way for Java to understand that, in my loop, I want to iterate only over all C objects in a list of A objects (which here could be either B or C objects).
Or maybe I don't use polymorphism in the right way or something like that...or maybe this is a true case of "instanceof" operator usage :)
(Yeah you're right, I don't like "instanceof" operator, it makes me think that I didn't do the things correctly so I need to fix them with casts and instanceof. It looks "dirty" to me, but maybe I'm wrong and it is very common to use it !)
Thanks !

There are sometimes cases where you need to know of which subclass an instance is. We can't really determine if your case is one of those. But if you need to implement this you should consider using the Visitor Pattern and only implement the method of your wanted subclass. This way you avoid the 'dirty' instanceof checks.

That sort of loop-and-filter isn't available in Java. As for whether you're using polymorphism correctly, it's hard to say without a bit more context. If B.childNodesC needs to use a method that isn't available on A, then you probably need to just use instanceof to filter out the Cs. But otherwise, a more purely OO approach would be to define a method on A that answers some filtering question, and then have B's map have A values. Something like:
A.isSomethingInteresting() -> false
A.doSomething() { ... }
C.isSomethingInteresting() -> true
C.doSomething() overrides { ... }
B.setNodes would then see if each A is something interesting, and add it to its map only if it does. It would then invoke doSomething() on each of its As, and polymorphism would take it from there.

That sort of construct is not possible in Java (at least through Java 6). That loop expects every object to be an instance of C and does not act as a filter (and it should not). In general, if you are looping through something you want to get everything. If you want to further filter, then that's a separate action. There is no shame in using instanceof to do that (any more than there is shame in checking a property of an object).

Related

Determine Object type with polymorphic calls [duplicate]

I have a List of interface type Criteria within my class Query.
List<Criteria> criteria = new ArrayList<Criteria>();
I have several concrete implementations of Criteria. I want to give Query a method that iterates through my criteria list, and depending on the concrete type, execute some logic.
I'm presently doing this with instanceof like so:
for(Criteria c : criteria) {
if(c instanceof ContextualCriteria){
// logic
}
...
}
Is this the only/best way?
Does the logic sensibly belong in the Criteria itself? If so, put it into the Criteria interface and implement it appropriately for each concrete class implementing the Criteria interface. This is obviously the nice polymorphic approach.
Unfortunately, in real life OO doesn't always work as simply as that - sometimes it doesn't make sense to put the per-type behaviour in the type itself, so you may need to use instanceof instead. You could potentially have a map from "criteria class" to some interface representing the action to take, but that could easily end up being even messier.
Double-dispatch via the visitor pattern can sometimes improve things a little - so the logic could still be in separate methods in your "calling" class, but each Criteria can call back to the right method via a single interface method. Personally I tend to find this increases coupling and gets ugly quickly, but others swear by it.
If the logic does not belong in the Criteria as Jon Skeet suggests, then you could use the visitor pattern.
In ConcreteCriteria:
public void accept(CriteriaVisitor v) {
v.visit(this);
}
In the Client code:
public void method() {
for (Criteria c : criteria) {
c.accept(this);
}
}
public void visit(ConcreteCriteria c) {
// do logic here
}
public void visit(Criteria c) {
// othervise...
}
This gets rid of the instanceof, but be wary, I have found that this pattern is difficult to understand if you are unfamiliar with the code.
Well, you can...
if (ContextualCriteria.class.equals(c.getClass()) {
... though it's just a fancier-looking way of writing instanceof. (Well, almost: this tests whether it is exactly the class, rather than the class of a subclass -- for that you want isAssignableFrom()).
The right way to get rid of the smell is to implement a polymorphic method in Criteria which is overridden in subclasses, for example.
An interface is halfway to the strategy pattern! To vary the logic based on type, push it behind the interface if possible, such that Criteria has a doLogic(). You can pass that method whatever parameters you might need to alter in the calling code, or return new information - that is very implmentation specific and hard to advice on from the code in question.
If all goes well, your calling code ends up
for (Criteria c : criteria) {
c.doLogic();
}
You could also implement the logic in the classes which implement Criteria
public interface Criteria {
public void logic();
}
Have several implemetations in classes like ContextualCriteria
And your loop would look clean:
for(Criteria c : criteria) {
c.logic();
}
You can also use:
for(Criteria c : criteria) {
if(c.getClass() == ContextualCriteria.class){
// logic
}
if ...
}
Note that Object#getClass() returns the runtime type of c, so you can't reliably use this if ContextualCriteria can be subclassed for example. To do this you would need to use Class#isAssignableFrom():
for(Criteria c : criteria) {
if(ContextualCriteria.class.isAssignableFrom(c)){
// logic
}
if ...
}
There is nothing wrong with it.
People who never used instanceof only wrote toy applications.

How to know the Dynamic type of a class?

My question is, how, or if its possible, to know the dynamic type of an object in the compilator.
I have this data
public abstract class accommodation;
public class Hotel extends accomodation;
public class Cabin extends accomodation;
accomodation [] array= new accomodation[x];
My actual problem is, can i get an array with only hotels from this?
One way is to use filter and map to first filter out all the objects that are Hotels, and cast to Hotel.
Arrays.stream(array)
.filter(x -> x instanceof Hotel)
.map(x -> (Hotel)x)
.collect(Collectors.toList());
Yes, there are a few ways to do this. One is to use the getClass() method. Because this is defined in the Object class, it can be called on every Java object.
System.out.println(myObject.getClass());
or even
if (myObject.getClass() == MyClass.class)
But if you only want to know whether an object is an instance of a particular class, you can write
if (myObject instanceof MyType)
which will return true if the class of myObject is MyType or any subtype thereof. You can use either an interface or a class for MyType here - even an abstract class.
However, as Tim pointed out in the comments, often there are better ways to design your program than relying on one of these ways of checking the class of an object. Careful use of polymorphism reduces the need for either of these.

Demand `T extends Comparable<T>` only for certain methods

I'm trying to write a generic class in Java. A few methods in that class require that T extends Comparable<T>. How can I make it such that T is required to be comparable only if one of those methods is used? Or maybe there's some other way I should organize my class?
Here's the class I'm trying to implement. Its and array that I plan to use on both comparable and non-comparable types.
// I know Java has its own containers, but this
// is homework and I'm not allowed to use them
class Array<T>
{
// Some methods that pose no
// special restrictions on T
// These require that T be comparable
public Array<T> union(...) {...}
public Array<T> intersect(...) {...}
}
You can hide type T for method. T of Test is not the same as T of CompareMethodhere.
public static class Test<T> {
<T extends Comparable<T>> void compareMethod(T t, Class<T> classt) {
}
void normalMethod(T t) {
}
}
Now example
Test<String> test = new Test<String>();//Comparable class
test.compareMethod("",String.class);//works fine
Test<Random> tes1t = new Test<Random>();//Non Comparable class
tes1t.compareMethod(new Random(),Random.class);//Compilation error here
tes1t.normalMethod(new Random());//Works fine
new Test<Random>().compareMethod("",String.class);// Not a good but can be valid
new Test<String>().compareMethod(new Random(),Random.class);//Compilation error here
Update:
After being cursed about this solution I did some search in java API and this practice gets followed for toArray() method
ArrayList<String> string = new ArrayList<String>();
string.toArray(new Integer[5]);<--Illegal however <T> is hide by toArray method
Edit: It looks like this is possible after all (see AmitD's post). But anyway, other possible solutions are
Refactor the methods requiring comparable into a subclass
Just use casts in the relevant methods, meaning that that part will only be checked at runtime.
It wont be possible through normal method such as using comparable.
It would be better if you share what is the exact requirement.
If Sorting in ArrayList/Arrays are your goal, then Comparing Non Comparable classes is useless. Sorting can only be done in objects of the same or sub types.
But if you are going to use compare for checking if the objects are equal or not then I'll suggest that you override equals(Object O) method.

Is there any way of imitating OR in Java Generics

EDIT: I changed a bit the example for getting the idea:
Like
<Integer or Float>
...without having to create a common interface and make a subclass for Integer and Float to implement it
If not, something like this would maybe have more sense and be useful
<E extends Number> <E = (Integer|Float)>
If ? is a wildcard why should not we allowed to restrict certain types?
It's not possible and I hardly see any value in it. You use generics to restrict type, e.g. in collections. With or operator you know as much about the type as much you know about the most specific supertype of both of them, Object in this case. So why not just use Object?
Hypothetical:
List<E extends String or Number> list = //...
What is the type of list.get(0)? Is it String or Number? But you cannot have a variable of such type. It cannot be String, it cannot be Number - it can only be... Object.
UPDATE: Since you changed your example in question to:
<Integer or Float>
why won't you just say:
<Number>
? Note that Number has methods that allow you to easily extract floatValue() and intValue(). Do you really need the exact type?
Note that you can use and operator:
<E extends Serializable & Closeable>
And that makes perfect sense - you can use variable of type E where either Serializable or Closeable is needed. In other words E must extend both Serializable and Closeable. See also: Java Generics Wildcarding With Multiple Classes.
In very extreme cases (pre-Java 7 without AutoCloseable), I would have liked to be able to do that, too. E.g.
<E extends Connection or Statement or ResultSet>
That would've allowed me to call E.close(), no matter what the actual type was. In other words, E would contain the "API intersection" of all supplied types. In this case it would contain close(), and all methods from java.sql.Wrapper and java.lang.Object.
But unfortunately, you cannot do that. Instead, use method overloading, e.g.
void close(Connection c);
void close(Statement s);
void close(ResultSet r);
Or plain old instanceof
if (obj instanceof Connection) {
((Connection) obj).close();
}
else if (obj instanceof Statement) { //...
Or fix your design, as you probably shouldn't have to intersect APIs of arbitrary types anyway
I don't see a real use for it... But anyways, I believe the closest you'd get to it is extending common interfaces for the possible implementations.

"instance of" "type of" What is the use case of this?

While doing some casual reading I came across an interesting quote by Scott Meyers
Anytime you find yourself writing
code of the form "if the object is of
type T1, then do something, but if
it's of type T2, then do something
else," slap yourself.
I was just wondering why Java has "instance of" operator when you could do the same thing by overridden methods? When is it actually used?
Sometimes you have to use objects whose behavior (e.g. source code) you do not control so you cannot always rely on object-oriented solutions to type-related matters. (Especially consider that authors of libraries cannot anticipate every use case you might have; of course, you could argue that extension and implementation provide workarounds but they require much more effort than direct type checking.)
The "instanceof" operator gives you a way to inspect the type of an object and act conditionally.
It's ideal to avoid it, but sometimes necessary.
Use of instanceof can interfere with the Open/Closed Principle (the "O" in SOLID). If you implement instanceof tests, then your class may need to be modified as new implementation classes are created.
However, it is sometimes necessary. For example, it can be used in implementations of the Object.equals() method. The argument is an Object -- so that the method may be overridden by arbitrary subclasses -- but you usually need to cast it to your class's type to compare.
I actually use it when I'm using a 3rd party library and classes are final (the jerks!).
An if-type-do-something in code is a sign that the do-something should be a method defined in the class or interface with overriding behavior. But that assumes you control the implementation. Sometimes you don't.
When I'm implementing equals() for a class Foo it often looks like this:
public boolean equals(Object o) {
if (o instanceof Foo) {
Foo that = (Foo) o;
[ compare this to that ]
} else {
return false;
}
Since I'm overriding equals the signature is forced on me, but I need to know whether I have an instance of Foo or not for a meaningful comparison.
For example :
public void eat(Eatable eatable){
if(eatable instanceof fruit){
//direct eat
}
}
class Eatable {
}
class Fruit extends Eatable {
}
While writing complicated class structure like in Wrapper design pattern, you never know what kind of object u will encounter. In these situation you check the object with instance of operator.

Categories

Resources