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.
Related
If i try to make array of Object class in java, it works fine
Object[] o = new Integer[]{1,2,3};
for(Object x : o)
System.out.print(x);
Output is: 123
I found out that you can also do
Object o = new Integer[]{1,2,3};
It doesn't give compile fail. I want to know that can we iterate through the Integers in reference 'o' ?
Then i tried this
class A{ }
class B extends A{ }
class App{
public static void main(String[] args) throws InterruptedException {
A a = new B[4];
}
}
But her A a = new B[4]; gives CF
Every single Object-type in Java inherits from the Object class.
So, basically: an Integer is an Object, which is why you can do this:
Object[] o = new Integer[]{1,2,3};
On the other hand, Arrays are Objects, too, meaning you can do this:
Object o = new Integer[]{1,2,3};
In the first example, the Integers are the Objects, in your second, the Object o is a reference to the Array of Integers
UPDATE: The reason between your A and B classes, you do have an Exception, is because even though each B is an A, the Array in which you store your B's is not an A.
Java arrays are covariant. Meaning that, You can use a Sub type in place of Type.
So if you have an array of "Type", you can actually fill that array with "SubType"'s. Well, any class in Java is a Subtype of Object. Hence no error in that case.
Object o = new Integer[]{1,2,3};
It doesn't give compile fail.
Again the same things, as Array is also an Object in the end, hence you are free to assign that to an Object.
I want to know that can we iterate through the Integers in reference 'o' ?
By default, Object is not iterable. Where as Array object is.
So before you going to iterate, you have to cast it to type Array.
Update :
But her A a = new B[4]; gives CF
Ofcourse that is not a valid declaration You should write
A[] a = new B[4]; // just to satisfy the compiler. At run time you are not allowed to store A's in it.
But if you are trying to achive the style
Object o = new Integer[]{1,2,3};
No that won't work here and you can only write
Object o = new B[4];
That is because array is a sub type of Object class and not A class.
The reason this is possible is that an array is a subclass of Object. However, by storing the array in o, the program "forgets" the fact that o is holding an array. For that reason, you cannot iterate over o.
The compiler will only allow you to do things that it "knows" you can do to that particular class. Here's an analogy: you want to haul 1 metric ton of sand for a few miles. Would you request a "vehicle," or would you specifically request some kind of truck that you knew would be large enough to haul the sand? If you request a "vehicle of some kind," for all you know they might send you a Prius, which obviously wouldn't do you any good - a Prius can't haul 1 ton of sand. In this case, the compiler would "complain" that there's absolutely no guarantee that you'll be sent a vehicle that has the capacity to do what you want.
Types work that way, too - by default, it's perfectly valid to upcast the array to type Object, since everything in Java is a subtype of Object. But, from the compiler's perspective, there's absolutely guarantee that you can iterate over something of that type, so it won't let you do that.
Suppose that I have these two objects:
Color c = new Color();
Shape s = new Shape();
and a method run() with some signature.
Now suppose that I want to call the run method sometimes with an object color and sometimes with an object shape. I could do something like these:
run(c);
public void( Color c){
//a bunch of code
}
or something like these:
run(s);
public void( Shape s){
//a bunch of code
}
As you can see, this is a bad solution because I'm creating the same method again but with different signatures and repeating a bunch of code 2 times. Is there any way to pass a generic object do this run method and then work with it? And of course no repeating code?
All objects in java extend (at the end) java.lang.Object class.
So, if you want a "generic" method, you should write something like:
public void methodName(Object o) {
...
}
But, make sure to make a casting accordingly inside this method.
You can use something like:
if (o instanceof Shape) {
Shape s = (Shape) o;
} else if (o instanceof Color) {
Color c = (Color) o
}
There are other options, for example passing an interface as a parameter of the method, and both classes should implement that interface.
Yes, you can use the Object class.
Every object has inheritance from the Object class, which means every object is a member of the object class.
If your method signature asks for an Object, then any object will be valid.
public void( Object o) {
// some code
}
Both shape and color are objects, so both will fit this method signature.
You have two options:
1. create a common interface of the objects and define the function with it:
public void run(CommonInterface c)
2. Accept Object as a parameter:
public void run(Object o)
The question that is asked is inviting very specific answers. As others have noted, if there is an interface that both objects can implement, that is the best approach. One can accept an Object as a parameter, and then (potentially) ascertain the type. However, this question is slightly problematic because it is not describing the actual desired result. It is the XY problem.
What happens when one then has a Texture object? Adjusting the code to continually deal with new types that do not implement a common interface will drive the maintenance costs very high. Therefore, one needs to look at the overall design. More than likely, the solution is that the run() should be implemented on each Object, and not be a method that takes the various object types directly.
As much as I do not really like the book, the maintenance example presented by this question is well described in Head First Object-Oriented Analysis and Design.
I think what matters here is what it is you want to do in // A bunch of code. For example, if you want to call .toString() method of Object, then you can pass object, but if you wish to do more than that, then you need to be more specific.
I think below example will be able to help you.
interface I {}
class A implements I {}
class B implements I {}
class Demo{
public static void main(String []args){
Demo d=new Demo();
d.run(new A());
d.run(new B());
}
public <T extends I> void run(T t){
// TODO do here you logic
}
}
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!");
}
}
}
}
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;
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());
}