Yaron Yosef
Yaron Yosef

Reputation: 447

arraylist of different classes without casting?

let me first say, i DID search for couple of hours and didn't find exactly what i need.

i need to run through array of class (apps) and use the variables and methods of the current app.

public class App {
   public final Integer number = 0;
}

public class Player extends App {
   public final Integer number = 1;
}

public class Navigation extends App {
   public final Integer number = 2;
}

public class Phone extends App {
   public final Integer number = 3;
}


private ArrayList<App> apps = new ArrayList<App>();

apps.add(new Player());
apps.add(new Navigation());
apps.add(new Phone());

if i do

apps.get(0).number //  = 0

i get the number of the parent (app)

if i cast it to player

(Player) apps.get(0).number //  = 1

i get the desired result

now, i want to run through all N apps (could be more than 3) in multiple places in the app but i don't want to do:

if (gun instanceof Player)
{
   Player p = (Player) apps.get(0);

}else if .... N times... in N places

i also don't want to make app an interface, cause i need the app defaults.

it's not necessary to use arraylist, if you have a better idea.

thanks in advance.

Upvotes: 1

Views: 138

Answers (4)

Vishesh Chandra
Vishesh Chandra

Reputation: 7071

You can create one interface with one method and implement that interface's methos in all class which all you are going to add in ArrayList then you can get directly value of number, check the sample it may help you.

import java.util.ArrayList;

public class Manager1 {

public static void main(String[] args) {
    ArrayList<App> list = new ArrayList<App>();
    list.add(new Playre());
    list.add(new Navigation());
    list.add(new Phone());

    System.out.println(list.get(0).getNumber());
}
}

interface App {
public abstract int getNumber();
}
class Playre implements App {
private final int number = 1;
@Override
public int getNumber() {
    return number;
}
}
class Navigation implements App {
private final int number = 2;
@Override
public int getNumber() {
    return number;
}
}
class Phone implements App {
private final int number = 3;
@Override
public int getNumber() {
    return number;
}
}

Upvotes: 0

NPE
NPE

Reputation: 500457

The fundamental issue is that in Java, data members are not polymorphic. This means that the following

public class Player extends App {
   public final Integer number = 1;
}

does not override App.number. What it does is create a new data member that is completely unrelated to App.number but is also called number.

Consequently, when you do obj.number, it is solely the compile-time type of obj that determines which number is accessed. The runtime type of obj plays no part in this.

To achieve polymorphic behaviour, use methods:

public class App {
   public Integer getNumber() { return 0; }
}

public class Player extends App {
   @Override
   public Integer getNumber() { return 1; }
}

...

An even cleaner way is to make App into either an abstract class or an interface, so that App.getNumber() is abstract and must be overridden in derived classes.

Upvotes: 1

Bohemian
Bohemian

Reputation: 425073

Use either a abstract method or an interface:

Abstract method:

public absteact class App {
    public absteact int getNumber();
}

public class Player extends App {
    public int getNumber() {return 1:}
}
// etc

Interface:

public interface HasNumber {
     public int getNumber();
}

public absteact class App implements HasNumber {
}

public class Player extends App {
    public int getNumber() {return 1:}
}
// etc

The interface version is preferable from a classical design perspective, but both are acceptable

Upvotes: 0

EdH
EdH

Reputation: 5003

Use a method instead of final variables. App.getNumber(), then each class can override the method in order to return the appropriate value. Each class can return the same constant, but define the constant as private and ensure you use the getter method

Upvotes: 5

Related Questions