creating a generic arraylist - java

this is a 2 part question.
I have two classes: Animal and Vehicle which I'll be instantiating as objects. Animal contains two instance variables: numLegs and animalName, and Vehicle contains one instance variable: numTires, both classes contain getters and setters.
I have a generic class Box that holds either an Animal or a Vehicle.
Suppose I want to create an Arraylist of boxes. Every Box in said Arraylist will hold exclusively type Animal or exclusively type Vehicle.
e.g: In the case of exclusively animals, this will look something to the effect of:
List<Box<Animal>> list = new ArrayList<Box<Animal>>();
list.add( new Box<Animal>( new Animal( "fluffy", 4 ) ) );
(1). What should the box class look like?
also, suppose I want to perform a getter on an animal from the list.
Such as: System.out.println(list.get(0).getName());
(2). how would I go about this properly?

I'm not exactly sure what you're after, but if you're wanting a generically typed Box class, it probably needs to look something like this:
public class Box<T extends SuperclassOfAnimalAndVehicle> {
T myModeOfTransport;
Box(T myModeOfTransport) {
this.myModeOfTransport = myModeOfTransport;
}
public T getModeOfTransport() {
return myModeOfTransport;
}
}
This line: list.get(0).getName() won't do however. You'll have to get the object that Box contains. So using my example, it would be list.get(0).getModeOfTransport().getName(), assuming Vehicle and Animal both have getName() methods.
All that being said, I'm really confused about why exactly this is necessary. Perhaps if you explained the bigger picture I could give you a more complete answer.

If you want to have a list containing two or more entities with nothing in common then you will always need to specialize your code to address each of them. This Box class is completlly useless.
Object o = list.get(0);
if(o instanceof Animal) {
System.out.println(((Animal)o).getName());
}

Related

Transformation of an object into a subclass object without loosing the references to the object

This is my first problem I can't solve by searching. It's a general OOP problem, but the code is in java. Perhaps I miss an essential point?
Assume there is a baseclass and a subclass. An object of the baseclass is in many lists. There is a transformer class with one duty to transform the object into a subclass object. The transformer should not know anything about the lists. But as a result of the transformation the new subclass object should be in all the lists. (replace the former base class object)
Can this be done somehow?
class BaseClass {
//
}
class SubClass extends BaseClass{
//
}
class Transformer{
BaseClass base;
public Transformer(BaseClass base){
this.base = base;
}
public void transform(){
//transforms the Object to a subtype-object
// ???
// (move the references of the old object to the new one)
this.base = new SubClass(); //something like this (but not so!!!)
}
}
class Programm{
private List<BaseClass> list1 = new ArrayList<>();
private List<BaseClass> list2 = new ArrayList<>();
private List<BaseClass> list3 = new ArrayList<>();
//many more Lists
private List<BaseClass> listn = new ArrayList<>();
public void main() {
BaseClass myObject = new BaseClass();
list1.add(myObject);
list2.add(myObject);
list3.add(myObject);
listn.add(myObject);
Transformer transformer = new Transformer(myObject);
transformer.transform();
//required result
// All Lists contain the transformed Object (from Type SubClass)
}
}
What you're trying to do is luckily impossible (imagine if your objects started changing classes in the middle of your code). You can create a subclass object based on a superclass object (if you can sensibly fill in any missing properties), but you can't turn an existing object into its subclass (such that the reference equality would work as you're hoping in your example code, i.e. converting myObject would affect all the lists).
I don't know how you came up with this idea, but somewhere along the way you've gone down the wrong path. If you tell us what you're trying to achieve, we can provide you with a better solution.
Edit:
Since you're doing checkers and you need to crown a piece, you have the simple choice of adding a boolean crowned property to pieces, and writing logic based on that.
In a more complex situation you could for example use the strategy pattern, where you would have a Piece class, and they would have a Type property that specifies the actual type of the piece. This way the object you put in lists (Piece) always stays the same, but if you replace its Type property, it would seem as if the piece magically changes it's type!

Is it okay for a class to have a field of its own type

I did the following, i got a stackoverflow error after some time, and I understand why it was.
public class Cat {
String name="default name";
Cat insideCat;
public Cat(){
System.out.println("Cat constructor");
insideCat = new Cat();
}
}
But what if I don't create a new Cat object within the constructor, but take a parameter of Cat type and assign it to the insideCat field.
public class Cat {
String name="default name";
Cat insideCat;
public Cat(Cat insideCat){
System.out.println("Cat constructor");
this.insideCat = insideCat;
}
}
I am just playing around with the code, just trying to find out what Java can do and cannot. In the second code, everything looked normal, until I started to test this class. I need a Cat object to create a Cat object (and to create this Cat object I need another Cat object...and it goes on). So technically I cannot test this class.
So my question is WHY does java allow to create an instance variable of its own type? I guess the whole purpose of a constructor is to initialize it's instance variables. So either I have to create a new object to initialize the insideCat or else I have to take Cat object from outside. Both doesn't seem to work.
What am I missing here. Is there any occurrence where instance variables of its own types can become useful, and can be used without any problem? Is it bad OOP practice to come up with classes like this?
Classes like this exist all the time.
Consider linked lists or trees, e.g.,
class ListNode {
ListNode next;
// Etc.
}
class TreeNode {
TreeNode left;
TreeNode right;
// Etc.
}
You wouldn't initialize the "child" objects in the constructor, you'd add them later.
In your example you'd need to have a method that created the insideCat at a later time. In general you wouldn't create child objects that had the exact same state, there'd be something to differentiate them either at construction time, in which case you could have a "oh god stop creating these now" condition, or while they were being added, e.g., you'd add them via a method and not in a constructor.
There is nothing wrong in having an instance member of same class.
an Employee has a manager and the manager is also an Employee
public class Employee{
private Employee manager;
//getters setters and constructor
}
There are many examples of self referencing data structures that are valid. Think of a LinkedList. Each LinkNode has a data field, and a pointer to the next LinkNode.
class LinkNode {
int data;
LinkNode nextLink;
public LinkNode(int d1) {
data = d1;
nextLink = null;
}
...
}
class LinkedList {
private LinkNode first;
...
}
Your StackOverflow problem stems from the fact that creating an instead of X requires the creation of another X, ad-infinitum.
Just think of your Cat example. Why would instantiating a Cat require of all things...another Cat!
There can be multiple constructors. Thus, you can have another constructor
public Cat(){...}
That would allow you to create an inside Cat. Afterwards you could create another Cat that contains the inside Cat. Obviously, the design might not be great here, depending on your needs. Dave Newton's answer about linked list is a great real world example of this usage.

Can you have an array of different kinds of objects?

I know that you can only have an array of a certain type (e.g. String, int, Student, etc.). I was wondering if this held true in the case of inheritance - i.e. whether or not a Bicycle object that extends Vehicle could be placed in a Vehicle array along with something else, like a Bus object.
Here's my code:
public class Test{
public static void main(String[] args) {
Bus bus1 = new Bus();
Bicycle bike1 = new Bicycle();
bike1.changeGear(true);
Bus bus2 = new Bus();
Vehicle[] myFleet = {bus1, bike1, bus2}; // Note that Vehicle is an abstract class
for (Bus v: myFleet){ // Trying to access every bus in the Vehicle array. I already
v.issueTicket(1.50); // tried to get the computer to treat myFleet as a Bus array - doesn't
System.out.println(v); // work, sadly.
}
}
}
Note that this is in the Java language
You have an array of a super type.
for iterates through ALL items in an iterable object (here array).
Since there can be Bicycle or Bus instances (or even other types, which are currently unknown) in the array, you cannot treat it as a Bus Array.
What you probably want is this :
for (Vehicle v : myFleet) {
if (v instanceof Bus) {
Bus b = (Bus)v;
b.doSomeSpecialThingsForABus();
}
}
There is no good other way around this except for the visitor pattern maybe.
If ClassTwo extends ClassOne and you make an array of ClassOnes, then you can add objects of ClassTwo to the array, however, you may only access members of ClassOne unless you cast.
Took me some time to get your point.
If you want to do something like this, you'll have to cast the Vehicle into a Bus.
However usually you should have an interface common to all vehicles.
As issueTicket() does not apply to bicycles you could probably think about not using the same interface for busses and bicycles at all.
Another idea would be to implement the issueTicket() method for bicecles just signalling an error as soon as it's called:
Vehicle[] myFleet = {bus1, bike1, bus2}; // Note that Vehicle is an abstract class
for (Vehicle v: myFleet){
v.issueTicket(1.50);
System.out.println(v);
}
However in my opinion this still feels like a design which could be better.
For me to provide some more suggestions it would be good to know the reason why those objects shall be stored within the same container.
Hope that helps.
Best regards,
Joerg
You can use
java.lang.Object[] myFleet;
But that could be too generic.
If your objects have a common interface (say Foo) then you could use
Foo[] myFleet;
Also have a look at some Java containers like ArrayList.
Yes...but
Yes, you can have an array of Vehicles, eg Bus1, Bus2 and Bike1.
...But that doesn't stop your Bike being a Bike, or turn it into a Bus. An array is a list of references to objects, it doesn't take a new copy of the object and turn it into the type of the array: the objects will still be instances of their original class
The Array can hold vehicles regardless of their sub-class, it doesn't change them into Buses, Bikes or Vehicles: the type stays the same.
You can try to cast a bike as a bus, however: if you accept that you'll lose any non-bus attributes. You can also use instanceof to decide if the Vehicle is a Bus already, or a Bike, and do conversion stuff if required
ie
for (Vehicle v: myFleet){ // For each vehicle in the fleet
Bus b = (Bus) v; // Turn the vehicle into a bus
b.issueTicket(1.50);
System.out.println(b);
}
Provided that bus and bicycle both either extend the same superclass or implement the same interface they can be placed into an array of the type of either the interface or the superclass.
To access those you can check if they are instances of any of the subclasses
for (Vehicle v: myFleet){
if(v instanceof Bus){
((Bus) v).issueTicket(1.50);
}
}
However using instanceof is not advised and in most cases it is better to find either an interface or superclass that describes the generic functionality required for all objects in the array.

Java: How to check what object an instance belongs to?

So apologies if this question has been answered already, although I did have an extensive look but couldnt quite find the answer. To sum up the situation I am trying to create a simulator program that deals with different predator and prey creatures and currently have the issue of getting each creature to check what type of creature it is next to, which I would prefer to do checking if the instance belongs to the same object.
So say for example I did this:
private class Creature {
...
Creature [] fish = new Creature();
Creature [] shark = new Creature();
Creature [] penguin = new Creature();
}
and then created several instances (creatures) of each type in a loop like so:
for (int f=1;f<rnd;f++) {
fish[f] = new Creature();
//set attributes of creature
and then so the program can tell where they are located in relation to each other I created a grid system like so:
Creature [][] gridloc = new Creature[x][y]; //relates to number of spaces tiles that determines movement.
Creature [] crloc = new Creature[tc]; //stores a reference to all creatures created.
...
crloc[tc] = fish[f]; gridloc[x][y]=crloc[tc] //or fish[f]
}
Anyway to sum even tho I summarised the code there quite a lot, that all works but when getting each creature to check next to it in gridloc for what is there e.g. a predator I am unsure of a way to check if it finds another creature to determine if that is an instance of the same object type or a different one. So something like:
if (!gridloc[x][y].getObject().equals(gridloc[x+1][y].getObject()) //if the current creature is not the same as the one next to it.
I am aware of things like instanceof but that only works with checking if an object is an instance of a class, not if a instance belongs to the same type of object. I also can't simply use fish[1].equals(fish[2]) because they have different attributes and that would check if they are exactly the same.
Any ideas/suggestions would be welcome. Thanks!
You need to look into Polymorphism (http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html). You declare a Creature as a base class (or interface) and extend/implement from Creature class for each type of a creature you have. Each subclass will implement it's own methods to override Creature and allow you to correctly use the methods and also to detect the type using the class metadata that each instance will have.
It's an issue with your design. You have to create a Super class called Creature and sub classes for fish , penguin and all others. Then create the arrays with those sub class types. Then you can do the instanceof checks with your adjacent objects of the grid.
This design is based on Polymorphism.
In the long run this is the best approach since code is more clean and structured. If you do this way, even after few years when you take a look at the code; still it will make sense.
One option (and perhaps the best in the long run, see answers by #AlexC and #Don) would be to make subclasses of Creature, called Fish, Shark, Penguin etc. Then you can use instanceof.
To combine that with polymorphism, you'd add a method public boolean eats(Creature other) As an aside, when I helped babysit a 4 year old his favorite game with little plastic animal figures was "what eats what" with loud screams of delight.
In Creature, the code would be return false; (though arguably fish eat fish?)
In Penguin, the code would be return other instanceof Fish;
In Shark, the code would be return true;
Another option would be to have a field of Creature that describes it. Maybe an enum, or a String for the latin classification names. Then, you could use something like genus.equals("Carcharodon") for Shark or latinName.contains("Spheniscidae") for Penguin.
Maybe creature should be an enum...
public enum Creature {
FISH(false), SHARK(true), PENGUIN(true);
private boolean isPredator;
private Point gridLocation;
Creature(boolean isPredator) {
this.isPredator = isPredator;
}
// ...getters/setters
}
with a separate world class for grid locations...
public class World {
List<Creature> creatures = new LinkedList<>();
public boolean isNearPredator(Creature c) {
for (Creature i : creatures) {
if (i.getGridLocation().distance(c.getGridLocation()) < 2
&& i.isPredator()) {
System.out.println("About to get eaten!");
}
}
}
}

Access variables outside a class that extends another class

How can I access variable outside a class that extends an other class that is used in an array list? I get an error that says that the variable does not exist in the extended class. Take a look, I want to access the variable members without having to declare it in my Object class:
public abstract class Object {
public int x, y;
}
public class House extends Object {
public int members = 10;
}
// Somewhere else
ArrayList<Object> list = new ArrayList<Object>();
list.add( new House() );
for (Object o : list ) {
o.members;
}
The problem is that in the RTS I'm writing, my Object class has over 40 variables, just because it doesn't work to declare them only in the sub class and access them from outside.
Hope you understand. How can I do this?
You can use instanceof and a cast:
for (Object o : list ) {
if (o instanceof House) {
h = (House) o;
h.members;
}
}
However, this is often considered bad design; you should consider defining an appropriate method in Object (which should really have another name, as others have pointed out) and override it in House. Then, you may call that method on an Object without knowing what kind of object it refers to, and if it is a House, the correct method will be called. (Learning how to do this properly, and when to do it, takes a bit of practice - google polymorphy and overriding.)
First do not name your class Object (see the comments). You cannot access member of an Object in your code, because Object has no field member, House has. But an Object does not have to be a House, so it is not guaranteed that it has member.
If you're sure that in this case youre Object is always a House, cast it:
((House) anObject).member;
This way the compiler assumes that you know more than he does about the actual class of the Object and handles it as if it was a House. You can use instanceof to check if the cast is valid.
Hope you understand that you are using the name for your class as 'Object', which is the parent class for all the classes in Java. Now in your environment there will be two Object classes one which java provides from java.lang.Object and another one you have created. So when you are trying to access your class object and trying to get the attributes of that, it is actually not your class object rather it is an instance of java.lang.Object and hence you are running into an issue.
You have to cast o to a House. E.g. ((House) o).members
just cast the member of arraylist like this
((House)o).members;

Categories