Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array of superclass objects. How to manage them as subclass ones?

Having these classes:

public abstract class Furniture

public class Chair : Furniture

public class Table : Furniture

public class Kitchen
{
ArrayList <Furniture> furnitures;
//other code
public void function ()
{
  Furniture furniture = furnitures.get();
  doSomethingInKitchen(furniture);
}


private void doSomethingInKitchen (Chair c);
private void doSomethingInKitchen (Table t);

}

I am looking for the best practice that assures me to manipulate the Superclass Furniture object as a subclass one (Chair or Table).

I tried with a simple cast, but when I call the function it operates with the Furniture Object, not with the Table or Chair one.

What I tried is something like:

for each Furniture in Array List
if(furniture.get() istance of Table)
{
currentFurniture = (Table) furniture.get();
}

else if (furniture.get() istanceof Chair)
{
currentFurniture = (Chair) furniture.get();
}
doSomethingInKitchen(currentFurniture)

I don't know if the problem is that currentFurniture is declared as

Furniture currentFurniture;

And so it won't be recognized as Chair or Table despite of the casting or if the design itself of the solution is wrong.

like image 973
EagleOne Avatar asked May 18 '16 19:05

EagleOne


2 Answers

Your cast is lost as soon as your reassign it to the common variable. You need handle each type separately:

for (Furniture furniture : furnitures) {
    if (furniture instanceof Table) {
        doSomethingInKitchen((Table)furniture);
    } else if (furniture instanceof Chair) {
        doSomethingInKitchen((Chair)furniture);
    }
}

Ideally though, you would avoid casting altogether and implement the differing logic on the subclass itself. For example:

abstract class Furniture {
    abstract void doSomethingInKitchen();
}

class Table extends Furniture {
    @Override
    void doSomethingInKitchen() {
        // Table-specific logic
    }
}

class Chair extends Furniture {
    @Override
    void doSomethingInKitchen() {
        // Chair-specific logic
    }
}

Now in your Kitchen you just do

for (Furniture furniture : furnitures) {
    furniture.doSomethingInKitchen();
}
like image 87
shmosel Avatar answered Sep 28 '22 01:09

shmosel


since you are inheriting Furniture class theres no need of implementing 2 methods for each chair and Table

private void doSomethingInKitchen (Chair c);
private void doSomethingInKitchen (Table t);

you can have a single method like this

private void doSomethingInKitchen (Furniture f);

and you can getRid of the casting in forloop and let the method do the casting.

private void doSomethingInKitchen (Furniture f){

   if(f instanceof Table){
   //code for the table 
   }else{
   //code for the chair
   } 

}
like image 39
Priyamal Avatar answered Sep 28 '22 01:09

Priyamal