TheLeonKing
TheLeonKing

Reputation: 3611

Java/Android: Define object with unknown type

I'm creating a game in Android Studio. The game has a Easy mode and a Hard mode (respectively hard=False and hard=True).

Both the Easy mode and the Hard mode have their own class. Both these classes contain the same functions, but their implementation differs. I'm calling the functions in these classes from my Gameplay class. This means that in every function in my Gameplay class, I have to do the following:

if (hard == True):
    HardGameplay gameplayMode = new HardGameplay();
else:
    EasyGameplay gameplayMode = new EasyGameplay();

functionResult = gameplayMode.myFunction();

However, instead of performing this if-else check in each function, I'd like to check this just once. Therefore, I have created a checkDifficulty() function, which I call at the start of my onCreate:

public ??? gameplayMode;
public Boolean easyOrHard() {
    if (hard == True):
        HardGameplay gameplayMode = new HardGameplay();
    else:
        EasyGameplay gameplayMode = new EasyGameplay();
}

The problem is, I don't know what type I should place at the ???. It should be either HardGameplay or EasyGameplay, but I don't know which of these two in advance. Putting Object there doesn't work either, because then, each function I call gives the error Cannot resolve method 'myFunction()'.

Does anybody know what to do? Or maybe there's an easier implementation I'm overlooking? Any help is greatly appreciated!

Upvotes: 1

Views: 1802

Answers (5)

Patrick
Patrick

Reputation: 831

You just have to use an interface :

public interface GamePlay {
    ... // Your different methods declaration
}

Your two classes will implement this interface :

public class HardGamePlay implements GamePlay {
    ... // You override  the methods here
}

public class EasyGamePlay implements GamePlay {
    ... // You override  the methods here
}

You can then use :

GamePlay gamePlayMode = easyOrHard();
public GamePlay easyOrHard() {
if (hard) {
    return new HardGameplay();
} else {
   return new EasyGameplay();
}

This is called Polymorphism : http://www.artima.com/objectsandjava/webuscript/PolymorphismInterfaces1.html

Upvotes: 4

Simon Tenbeitel
Simon Tenbeitel

Reputation: 877

You need Polymorphism.

So create a superclass called GamePlay and make HardGamePlay and EasyGamePlay extend these classes. This superclass defines the functions which will be implemented by its subclasses

public abstract class GamePlay {
    public abstract void myFunction();
}

public class HardGamePlay extends GamePlay {
    public void myFunction() {
         //your code here
    }
}

Then you can use

public GamePlay gamePlayMode

In your GameActivity do this:

Gameplay gameplay = null;
if (hardmode)
    gameplay = new HardGamePlay();
else
    gameplay = new EasyGamePlay();

Upvotes: 7

liminal
liminal

Reputation: 1164

Basically you got 2 answers so far above:

1) use abstract base class with abstract myFunction()

2) have a common interface with myFunction() that both EasyGameplay and HardGameplay implement

The way you decide between the two approaches is how much common implementation data and behavior is between the two: if at least one method implementation (not just method signature) can be shared and/or the classes have the same class member attributes, you should go with an abstract superclass and make only myFunction() abstract. Otherwise, use a common interface which defines only method signatures that the two implementors (EasyGameplay and HardGameplay) will implement.

Upvotes: 2

Bogomil Dimitrov
Bogomil Dimitrov

Reputation: 139

As Simon said, you can create a superclass that is being extended by HardGamePlay and EasyGamePlay. This would work if both classes have the same method nomenclature.

However, if the EasyGamePlay and the HardGamePlay classes have different methods you can try using Object, but keep in mind that you need to cast it to the appropriate class before calling the method.

public class Person {
    public void sayHello() {
        System.out.println("I am a person");
    }
}

public class Dog {
    public void bark() {
        System.out.println("Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Object thing = new Dog();

        //This won't work as the program 
        //does not know which instance to call
        //thing.bark();

        if(thing instanceof Person) {
            ((Person)thing).sayHello();
        } else if(thing instanceof Dog) {
            ((Dog)thing).bark();
        }
    }
}

And still, the best way to go is to use polymorphism so you avoid using Object variables/fields. If you cannot use polymorphism consider reviewing your software architecture

Upvotes: 1

SomeJavaGuy
SomeJavaGuy

Reputation: 7357

If both classes would contain the same methods, you could simply create a Game interface, which you could use as a variable type.

public interface Game {
    void methodA();
    void methodB();
}

Both modes could now implement from this interface

public class HardGameplay implements Game{
    @Override
    public void methodA() {
        // Do something
    }

    @Override
    public void methodB() {
        // do something
    }
}

public class EasyGameplay implements Game{
    @Override
    public void methodA() {
        // Do something
    }

    @Override
    public void methodB() {
        // do something
    }
}

You could now create a variable Game and assign the specific type of the mode to it. Due to both of them having a common interface you can still acces both classes the same way, as it can be seen in the method doSomethingHere

public class GamePlayManager {
    private boolean hardMode;

    private Game gameMode;

    public GamePlayManager(boolean hardMode) {
        this.hardMode = hardMode;
    }

    public void createGame() {
        if(hardMode) {
            gameMode = new HardGameplay();
        } else {
            gameMode = new EasyGameplay();
        }
    }

    public void doSomethingHere() {
        gameMode.methodA();
    }

}

Upvotes: 3

Related Questions