PDA

View Full Version : Take any object


webguy08
04-07-2009, 06:43 PM
Hi all,
As part of my program design one of my classes creates a new instance of a different class and then [needs to] store this new object into an ArrayList. However, this new object can be one of many different classes. As a result, if I want to add this object to the ArrayList, I can't because the ArrayList can only take one type of object. Is there anything else I can use, or is there a way to overcome this?

I've tried the following type of code as an alternative:
Class2 class3 = new Class3();
Class2 class4 = new Class4();
Class2 class5 = new Class5();
However this does not work because Class2 is not of type Class1 etc.. I then thought that Class1 could hold an ArrayList of type Class2 and store these, but that doesn't seem to be working either. But I need to achieve something along these lines :(

Here is how it (what I just explained) would look on an object diagram:

Class 1 (holds an ArrayList of type Class2)
|
\|/
Class2 (creates one of the other classes)
/ | \
\/_ \|/ _\/
Class3 Class4 Class5


Thanks for any help :thumbsup:

brad211987
04-07-2009, 09:23 PM
Post the relevant code so we can see where you are going wrong. A few questions:

Does Class2 extend Class1?
Do the rest of the classes extend Class2?

There are a few ways that you can approach this, you can use Class2 as an abstract class, or use it as an interface and use generic's to build the type in your ArrayList etc.... Either way, lets see what you have so we know which direction to take.

webguy08
04-07-2009, 11:24 PM
Below is the code from the class. This fits with my original post where I have provided a class diagram.

This would be Class1 from the original post:

import java.util.*;
public class Simulator {
private ArrayList animals;

public Simulator() {
Animal animal = new Animal();
animals.add(animal);
}
...


This would be Class2 from the original post:

import java.util.*;
public class Animal {

private double probability;
private Animal animal;

public Animal() {
setProbability();
if (probability <= 0.15) {
Animal animal = new Fox();
}
if (probability > 0.15 && probability <= 0.50) {
Animal animal = new Rabbit();
}
}

public void setProbability() {
Random number = new Random();
probability = number.nextDouble();
}
...


This would be Class3 from the original post:

public class Rabbit {
public Rabbit() {
}
...


This would be Class4 from the original post:

public class Fox {
public Fox() {
}
...


Class2 doesn't extend Class1. It is important that Class1 is concrete as it performs many tasks throughout the program.
None of the classes extend eachother.

Thanks for the help :)

brad211987
04-08-2009, 12:42 AM
You will need to make your individual animal classes extend the Animal class. If there is going to be common functionality between them, you could make it an abstract class, and put the common code in the Animal class and let the individual classes implement the instance-specific code.

webguy08
04-08-2009, 01:34 AM
In the Simulator class, when I eventually take the Fox and Rabbit objects out of the Arraylist will I be able to call their methods along with the Animal class' methods?

brad211987
04-08-2009, 01:38 AM
Yes, you may have to cast them to their individual classes, or define the methods you want in the abstract class.

webguy08
04-08-2009, 01:42 AM
I have made the Animal class a super class, however I get an error in the Simulator class at the point which I have shown in the code below.


import java.util.*;
public class Simulator {

private int tick;
private int tickTime;
private ArrayList<Animal> animals;

public Simulator() {
Animal animal = new Animal();
animals.add(animal); // Null pointer exception
}
...


This relates to my original problem where I need to store objects of different types into an ArrayList, or something similar.

brad211987
04-08-2009, 01:54 AM
You haven't created the ArrayList. You will need to create your ArrayList before using it:

animals = new ArrayList<Animal>();

webguy08
04-08-2009, 03:44 AM
Ugh I'm so stupid lol

Thanks for the help :thumbsup:

webguy08
04-08-2009, 06:23 PM
I have come across an error :(
When the Simulator class calls the Animal class to create a new Animal (either a Fox or Rabbit) I get a StackOverflowError, and it highlights the constructor in the Animal class at the line: super();. From what I have read I have gathered that this is because the Animal class is calling the Fox/Rabbit class, and then the Fox/Rabbit class calls the constructor of the Animal class, thus it is an infinite loop. Is this correct? So now, I have hit a brick wall lol. Are there any solutions to this, or is this a dead end?

TheShaner
04-08-2009, 07:53 PM
I think you're a bit confused here.

You should have the Fox and Rabbit classes as the children, while the Animal class is the parent.

So:
public Fox extends Animal
{
public Fox()
{
super(); // Calls Animals constructor
}
}

You would then instantiate your Fox object like so:
Fox myFox = new Fox();
You will not be instantiating the Animal class directly. Your Fox and Rabbit classes will do that using their super() directive.

-Shane

webguy08
04-08-2009, 11:30 PM
Oh, I forgot to mention that I updated the code from what is shown in the original post. The Simulator class is the same as the original post, the Animal class is a superclass of the Fox and Rabbit classes. What you have written is exactly how my Fox and Rabbit classes look like. The Simulator class calls the Animal class to create either a Fox or Rabbit, and then stores that Animal in its own ArrayList. The code is exactly the same as the original post except for the creation of the Animal superclass, and the Fox and Rabbit classes using 'extends'.

Sorry I didn't mention the new code :o

TheShaner
04-09-2009, 02:06 PM
Your Animal class should not be instantiating Fox or Rabbit classes. A parent class should NEVER instantiate a child class. A parent object is usually more of a container object for which to build up your children classes, and generally has no knowledge of its children.

Your Simulator class should have an array list declared as so:
ArrayList<Animal> animalList = new ArrayList<Animal>();
Then the Simulator class should add your animals like so:
animalList.add(new Fox());
animalList.add(new Rabbit());
-OR-
Fox fox1 = new Fox();
Rabbit rabbit1 = new Rabbit();
animalList.add(fox1);
animalList.add(rabbit1);
This works because the Array List is expecting an Animal object, and since Fox and Rabbit are subclasses of Animal, it's allowed.

If you wanted to grab the Fox from the Array List, you would do something like:
Fox foxy = (Fox) animalList.get(0);
You're getting the Animal object from the first index of the list and casting him back to his original object name. If you don't do this, you won't have access to the variables and methods contained in Fox and could only use the variables and methods in Animal.

-Shane

webguy08
04-09-2009, 02:20 PM
Excellent post TheShaner! I fully understand that now :thumbsup: