How does inheritance work with for-each loops? - java

How does inheritance work in relation to a for-each loop? Imagine I have two classes: SubClass and SuperClass, and I have the following ArrayList.
/**
* Containes both SuperClass and SubClass instances.
*/
ArrayList<SuperClass> superClasses = new ArrayList<SuperClass>();
Is it possible to iterate over superClasses in such a way as to only select subClasses.
The following:
for(SubClass subClass : superClasses){
// Do Foo
}
does not do this.
The following is the only thing that I could get to work:
for(SuperClass superClass : superClasses){
if(superClass instanceof SubClass){
// Do Foo
}
}
However I do not want to use instanceof unless absolutely necessary, as I keep reading everywhere (StackOverflow, Oracle Tutorials etc) that one can almost always find a better solution that increases encapsulation. Is there a more elegant way of doing this?

Well you could write a helper method to hide the instanceof test... Guava has a method like this, for example, in Iterables.filter, which you could use like this:
for (SubClass subclass : Iterables.filter(superclasses, SubClass.class)) {
...
}
It's only moving the instanceof check though really - it's not getting rid of it. Fundamentally you need that check, because something's got to do the filtering.

The first approach (for (SubClass subClass : superClasses)) cannot work as the compiler cannot ensure that there are only objects of tyoe SubClass in there.
In Java (without external libraries) it is not possible to preselect on the Class. Therefore the instanceof is the normal way to do this.

instanceof would work absolutely fine in this situation. But if you really do have reasons for not using it you could always give the superclass some variable, Boolean skipMe = true, and change that to false in the subclass if you wanted.
But I suggest using instanceof

I recommend to manage a separate List which only contains instances of SubClass, if possible.

Related

Using instanceof to seperate classes in an ArrayList

apologies if this is simple or has been answered before, I'm new to Java and in my research I can't find too much on this issue and have not yet found a solution.
I have an ArrayList with multiple classes that all share a common Interface, in this example the interface is called "Packable". I'm trying to create a method that takes a class parameter and sweeps through each element of this ArrayList, returning a new list containing all the items in the original list that are of the same class as the reference parameter.
This is my code so far, trying the instanceof method:
public List<Packable> getOfType(Packable reference){
List<Packable> typeOfItems = new ArrayList<>();
for (Packable item: itemsStored) {
if (item instanceof reference){
typeOfItems.add(item);
}
}
return typeOfItems;
}
This is throwing an error as it doesn't yet recognise reference as a class. This question mentions a method isAssignableFrom with the answer stating: "When using instanceof, you need to know the class of B at compile time. When using isAssignableFrom() it can be dynamic and change during runtime." (Thanks Marc Novakowski)
I understand that given the parameter the class isn't known at compilation and as such I've tried implementing isAssignableFrom and can't really seem to get it to work. The IDE doesn't really recognise or suggest it, and there isn't too much about the method online. I've tried implementing it the way the JavaDocs suggest but this isn't working either:
if (reference.isAssignableFrom(item.getClass())){
typeOfItems.add(item);
}
Any help or advice on methods to look into would be greatly appreciated. Thanks for reading the question, and again apologies if this is simple or has been answered elsewhere and I've just missed it. Thanks everyone
I'm not sure what Packable is, but you appear to be confused about a few concepts here.
In java, Packable reference does not represent the Packable concept. It represents a specific instance of Packable (or null).
In other words, given Dog dog, that means dog is some specific dog. Not 'the general concept of a dog'. We know that the specific animal that dog is referring to is, at least, a Dog. It could be Fifi, the neighbour's schnauzer.
instanceof, on the other hand, is about the general concept of things: if (fifi instanceof Dog) is how you're supposed to use it. You're more or less attempting to do the equivalent of if (fifi instanceof rover) which just doesn't make sense. How can one dog be 'an instance' of another? It's not that the answer is 'true' or 'false', but that the very question doesn't even make sense, which is why javac doesn't compile it. It has no idea what this even means.
Java, being java, makes objects of many things. Notably including the very notion of things. Thus, there is the class java.lang.Class, instances of which represent classes. A bit of alice-going-down-the-rabbit-hole thing is happening here: Classes as a concept are also represented as instances of the java.lang.Class class.
A class OBJECT (so, an instance of java.lang.Class) has the .isAssignableFrom method. This in fact takes another j.l.CLass as argument, it's for checking if one type is a subtype of another. In that sense, the question linked is needlessly confusing - you're really looking for the instanceOf method (there is an instanceof language construct, but the j.l.Class class has an isInstance method, which is unrelated, other than that they roughly accomplish the same goal: Check if some INSTANCE is of a type that is equal to, or a subtype of, some TYPE.
This is an example of how to use it:
Class<?> c = Number.class;
Object o = Integer.valueOf(5);
System.out.println(c.isInstance(o));
this is more or less equivalent to:
Object o = Integer.valueOf(5);
System.out.println(o instanceof Number);
Except now the Number part no longer needs to be written at 'write the code' time, you can supply it, say, read it from a parameter. You'd have to, of course, dynamically construct the Class instance. You can do so either by string-lookup, or by getting the actual type of an actual object. For example:
String input = scanner.next(); // user types in "java.lang.Number"
Class<?> c = Class.forName(input);
Object o = Integer.valueOf(5);
System.out.println(c.isInstance(o));
Or:
Object i = Integer.valueOf(5);
Object d = Double.valueOf(10);
Class<?> c = i.getClass(); // will be java.lang.Integer.class
System.out.println(c.isInstance(d)); // false
But doing this latter bit is really dangerous. Often i.getClass() returns some hidden impl detail subtype (java is hierarchical and object oriented, anywhere, say, an ArrayList is needed, someone is free to make a new class: class MyVariantOfArrayList extends ArrayList, and use that - now you write ArrayList foo = getList(), but foo.getClass() doesn't return ArrayList - no, you invoke that method on the object the foo variable points at, so, it'd be MyVariantOfArrayList.class, not ArrayList.class.
It's possible Packable itself represents a type. But then it either needs to also have isInstance and isAssignableFrom and such (and you need to start questioning why you're badly reinventing the wheel here - java.lang.Class already exists!), or it needs a .getRepresentedClass() method. You can't call it .getClass(), as the JVM has already given all objects that method, and it would return Packable.class itself.

Using superclass type for subclass instance

I know this question has been asked a lot, but the usual answers are far from satisfying in my view.
given the following class hierarchy:
class SuperClass{}
class SubClass extends SuperClass{}
why does people use this pattern to instantiate SubClass:
SuperClass instance = new SubClass();
instead of this one:
SubClass instance = new SubClass();
Now, the usual answer I see is that this is in order to send instance as an argument to a method that requires an instance of SuperClass like here:
void aFunction(SuperClass param){}
//somewhere else in the code...
...
aFunction(instance);
...
But I can send an instance of SubClass to aFunction regardless of the type of variable that held it! meaning the following code will compile and run with no errors (assuming the previously provided definition of aFunction):
SubClass instance = new SubClass();
aFunction(instance);
In fact, AFAIK variable types are meaningless at runtime. They are used only by the compiler!
Another possible reason to define a variable as SuperClass would be if it had several different subclasses and the variable is supposed to switch it's reference to several of them at runtime, but I for example only saw this happen in class (not super, not sub. just class). Definitly not sufficient to require a general pattern...
The main argument for this type of coding is because of the Liskov Substituion Principle, which states that if X is a subtype of type T, then any instance of T should be able to be swapped out with X.
The advantage of this is simple. Let's say we've got a program that has a properties file, that looks like this:
mode="Run"
And your program looks like this:
public void Program
{
public Mode mode;
public static void main(String[] args)
{
mode = Config.getMode();
mode.run();
}
}
So briefly, this program is going to use the config file to define the mode this program is going to boot up in. In the Config class, getMode() might look like this:
public Mode getMode()
{
String type = getProperty("mode"); // Now equals "Run" in our example.
switch(type)
{
case "Run": return new RunMode();
case "Halt": return new HaltMode();
}
}
Why this wouldn't work otherwise
Now, because you have a reference of type Mode, you can completely change the functionality of your program with simply changing the value of the mode property. If you had public RunMode mode, you would not be able to use this type of functionality.
Why this is a good thing
This pattern has caught on so well because it opens programs up for extensibility. It means that this type of desirable functionality is possible with the smallest amount of changes, should the author desire to implement this kind of functionality. And I mean, come on. You change one word in a config file and completely alter the program flow, without editing a single line of code. That is desirable.
In many cases it doesn't really matter but is considered good style.
You limit the information provided to users of the reference to what is nessary, i.e. that it is an instance of type SuperClass. It doesn't (and shouldn't) matter whether the variable references an object of type SuperClass or SubClass.
Update:
This also is true for local variables that are never used as a parameter etc.
As I said, it often doesn't matter but is considered good style because you might later change the variable to hold a parameter or another sub type of the super type. In that case, if you used the sub type first, your further code (in that single scope, e.g. method) might accidentially rely on the API of one specific sub type and changing the variable to hold another type might break your code.
I'll expand on Chris' example:
Consider you have the following:
RunMode mode = new RunMode();
...
You might now rely on the fact that mode is a RunMode.
However, later you might want to change that line to:
RunMode mode = Config.getMode(); //breaks
Oops, that doesn't compile. Ok, let's change that.
Mode mode = Config.getMode();
That line would compile now, but your further code might break, because you accidentially relied to mode being an instance of RunMode. Note that it might compile but could break at runtime or screw your logic.
SuperClass instance = new SubClass1()
after some lines, you may do instance = new SubClass2();
But if you write, SubClass1 instance = new SubClass1();
after some lines, you can't do instance = new SubClass2()
It is called polymorphis and it is superclass reference to a subclass object.
In fact, AFAIK variable types are meaningless at runtime. They are used
only by the compiler!
Not sure where you read this from. At compile time compiler only know the class of the reference type(so super class in case of polymorphism as you have stated). At runtime java knows the actual type of Object(.getClass()). At compile time java compiler only checks if the invoked method definition is in the class of reference type. Which method to invoke(function overloading) is determined at runtime based on the actual type of the object.
Why polymorphism?
Well google to find more but here is an example. You have a common method draw(Shape s). Now shape can be a Rectangle, a Circle any CustomShape. If you dont use Shape reference in draw() method you will have to create different methods for each type of(subclasses) of shape.
This is from a design point of view, you will have one super class and there can be multiple subclasses where in you want to extend the functionality.
An implementer who will have to write a subclass need only to focus on which methods to override

Java - data structure to contain a set of different subclasses of the same superclass

I need to have some sort of data structure that can contain heterogenous subclasses of the same superclass, all of which I have implemented myself.
So far, I am attempting to have an ArrayList<SuperClass> list = new ArrayList<SuperClass>();
and then, I am assuming I will be able to cast each slot of list into either of the subclasses, but this is not working out so well.
I need an efficient way to do the aforementioned.
Thanks!
You can do it with any data structure that exists, I would recommend a List or a Set. For instance:
Collection<Super> supers = new ArrayList<Super>();
Now when you say this:
I am assuming I will be able to cast each slot of list into either of
the subclasses,
That is an invalid assumption. The collection will hold any object that extends Super however you cannot arbitrarily cast each element into whatever you want. You would need to do an instanceof test on each element if you are looking for that type of functionality, example follows:
for(Super currentSuper : supers)
{
if(currentSuper instanceof SubA)
{
SubA subA = (Suba) currentSuper);
// do stuff with subA
}
else if(currentSuper instanceof SubB)
{
SubB subB = (SubB) currentSuper);
// do stuff with subB
}
}
Scope as need be.
Now on the point of Vlad:
and much better design would be not to test what the actual class is,
but just to call a virtual method, which will do the right thing in
any case
If you can guarantee the functionality of all potential sub-classes and have no issues with people overriding your classes (in the event you haven't marked them final) you do not need to do the instance of test. Instead your code could be as simple as:
for(Super currentSuper : supers)
{
currentSuper.doSomethingNifty();
}

How to get the object class in Java?

What is the best way to get the class of an instance ?
What is the recommended way ? and what are the differences (performances) between :
Compare the class
if( this.getClass().equals(MyClass.class) ){
which seems to be the same as this.getClass() == MyClass.class (or perhaps using Class.forName("com.test.MyClass"))
Test the instance of (seems to be the more readable)
if( this instanceof MyClass ){
Test the instance using class
if( MyClass.class.isInstance(myInst) ){
I would recommend this.getClass().equals( MyClass.class) when you want to match a class exactly because "someString" instanceOf Object will produce true because String class is subtype of Object.
This is checking is a relationship between any instance and the class.
In your case any subclass of MyClass will produce true
instanceof tests whether the thing on the left is an instance of the type on the right or some subtype.
getClass() == ...tests whether the types are identical.
Option one only tells you if the class is exactly what you are testing. This is usually not very useful. For example, it's completely pointless for interfaces. If this is actually what you want to do, you can probably use == unless you're messing around with different ClassLoaders, in which case there may be more than one instance of each Class object.
Option two tells you whether the object is statically assignable to the given class (i.e. can be cast to it).
Option three does the same as two, but using the reflection API. You'll only need this if you're doing dynamic typing. The built-in instanceof is more readable and should be much more efficient.

Class Casting Exception in Java

I'm having a problem with casting Classes to each other.
To explain it in more detail, take a look at this image.
In my code, I do SkillBase s = new SkillBase(); and then set some values in that class.
Then I try to do Subclass sub = (Subclass)s; but when running it it gives a ClassCastException.
I added a small debug part, which checks if it's instanceof which returns true.
I've tried the google, saw some questions on here aswell and read them (none of them had an answer that was for me)
So, what do I do?
SkillBase is not an instance of Subclass, so why do you think casting will work? Try with this:
SkillBase s = new Subclass();
Subclass sub = (Subclass)s;
which will succeed. Also I think you are not correct with instanceof, I am certain that:
s instanceof Subclass
yields true in the the code above but false in your case.
Thinking in real world terms: you can always cast Dog to Animal because every dog is an animal*, but casting Animal to Dog might fail since some animals aren't dogs.
* in fact, compiler does that for you, it is known as polymorphism
You can only up-cast i.e. assign sub classes to super class references. Think of it this way: Subclass extends the Superclass by adding a new method f(). Now Superclass doesn't know any thing about f() and hence the problem.
You're probably using instanceof wrong.
The runtime is right to crash, as SkillBase is not a Subclass.
The other way around is true.
s can't be cast to Subclass because it wasn't instantiated as a Subclass. It is a Skillbase. If you want to use a Subclass why not just instantiate it?
Subclass s = new Subclass();
You can still set the parameters you want because they hare inherited by Skillbase and the cast is no longer necessary.
The problem is that you are not using casting properly. A class can always be cast as its parent, but not the other way around. The concept is that a child class (by definition) knows the structure of the parent, and (by definition) already supports all the signatures in the parent. Consequently, the parent is a subset of the child.
The inverse, however, is not true. The parent class knows nothing about the child class and/or whether the child has added extra signatures to its structure. Consequently, there is no way to tell the compiler to treat the parent as a child and make available all the methods that the child has in the parent.
It layman speak, water (child) is a liquid (parent), but not all liquids are water. Consequently, any measurements you want to make on liquids (ie: quantity, viscosity, etc) hold true for water as well, but not the other way around (ex: density of water is completely different than density of oil).
So to bring this all back to your situation, you can cast Subclass as a Skillbase but not the other way around.
Subclass instanceof Skillbase == true
(Skillbase) new Subclass() - also valid
(SKillbase) new Sub#2 - also valid
etc...

Categories