Yes. Look at the A, B, C, D classes example. C extends B, and B extends A, so C is-a B and it is also an A. By default, all classes extend the Object class already.An example for a higher level class might be life form, Animal might be a lower class than life form, although I'm not sure that if LifeForm was being used and Animal was an extension of LifeForm, would Pig then be an extension of Animal? (Can you have 'nested' extensions?
Ok, so yes, we can use the instanceof to do some Animal-specific thing, but it is more commonly used (for situations like this) to perform "casting". Casting lets us restore the real type of the object. I'll explain with code:We / The Java program will know this because we're going to use the
if(animal instanceof Pig)
Statement.... without this statement would it know? Or rather, this statement is just to enable us to return certain thing's based on what class / object is returned by the list....
So at RunTime the animal is what ever sub-class was entered by the user, cow / sheep / pig... So for example say the PigClass had a method called makeBacon(), at what point could we use
animal.makeBacon();
I'm assuming that this is somehow wrong, because it would be a bit odd to have all the pig's, cow's and sheep to be called 'animal'.
It really does make sense, I think that I understand how the logic work's within the examples given and on a more general level. There are still some uncertainties about details though, such as the makeBacon() example above.
So, as you can see, we can determine the real type of the object at compile time, but we need to check the type with the instanceof operation. If we don't you will get a compiler warning (depending on your IDE), and a runtime exception will be thrown if the animal is anything other than a Pig, so it is best to check with the instanceof operation first.Animal animal = animalList.get(i); if(animal instanceof Pig) { // Check the type of the animal Pig pig = (Pig)animal; // Cast the animal into a Pig variable type pig.makeBacon(); // Call the makeBacon() method with the pig variable }
Your analysis of what the program was correct up until this point. Ok, there are two concepts at work here: "variable scope" and "pass-by-value". First of all, "variable scope". When you declare a new variable within a set of curly brackets (ie: a "block of code"), that variable only exists within that block of code (as well any nested blocks of code). So the variable in the promptUser and the createAnimal() methods are not the same. When the promptUser method ends, the animal variable inside of it gets destroyed. The VALUE of the variable is returned from the method. We then set the VALUE of the userAnimal variable in the main to the VALUE returned by the promptUser method. We then send the VALUE of the userAnimal variable to the createAnimal() method. In the createAnimal() method, a brand new String animal variable is created (which will be destroyed when the createAnimal() method ends), and its value is set to the VALUE which was sent to the method. This behavior is known as "pass-by-value", meaning we are passing around the value of variables, instead of the reference to variables. Now, String is an object, and most objects are passed by reference instead of value. But String is different because of something called immutability, which just means it cannot be directly edited, so the values are passed instead of the object references. I'm not going to get into immutability right now, because it can be confusing. Just know that String are passed by value, not reference.I'm a little unsure here actually with how the variable userAnimal and promptUser animal is being passed around.
In the main method the userAnimal is created from the promptUser method - so the animal String variable from promptUser is replaced by the user defined userAnimal.... But in the FarmClass our createAnimal method has an input of String Animal - this input is the animal variable from the promptUser class, that is now the userAnimal.
So - the animal variable still exists within the FarmClass - but it's value has been replaced by the value input by the user. This happens before the code from the createAnimal method is processed, so by the time the process get's to createAnimal the variable animal is the animal that was input by the user. We can use the animal variable in the createAnimal class because it's returned by it's method.
When you declare a local variable in a method, you must set it to something. Null means it has no value and has not been initialized to anything. The tempAnimal variable has no instance associated to it. If you tried to call any of the Animal class's methods on it, you will get a NullPointerException at runtime, telling you that tempAnimal has no value. The "variable type" is still Animal, but it has no value. So if you want a local variable to have no value at the start of a method, you set it to null.So now we're in the createAnimal class, the user having specified which they'd like to create. We create a tempAnimal and assign it's value to null. This is because we've already used the variable animal in the class (as input) so need to have another variable that can be used within the createAnimal class. Although tempAnimal is of type Animal where as animal is a String - so hmm. So what is tempAnimal at the stage of
Animal tempAnimal = null;
It's value is null - but is it an 'animal' ? Has this in some way declared an abstract class? I know it's not with the 'new' operator, but still. So at this point is tempAnimal an Animal, and because it's abstract its value is null?
This is the pass-by-reference that I mentioned. animal is an object (and not immutable), so when you pass the object to the animalList.add() method, you are passing the reference in memory of the initialized object itself. When you pull the object out with the get() method, you are also pulling out the reference in memory to the object. So the same reference which you put into the list at a certain index will be the one which comes out. Any changes you make to the object will affect all variables which have a reference to that object in memory. No converting ever happens, because java does not need to.So does Java convert them as it's putting them into the list or as it's pulling them out?