1

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!

1

5 Answers 5

7

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();
Sign up to request clarification or add additional context in comments.

2 Comments

This does seem like the most efficient way to solve my problem, thanks! However, there is one tiny problem. I'm doing this in Android Studio, and my Gameplay.java class is called from my GameplayActivity.java: Gameplay gameplay = new Gameplay(); gameplay.initializeGame(this, this.getApplicationContext());. However, it's not possible to instantiate an abstract class. Is there a way around this?
You have to instantiate the subclass. Gameplay gameplay = new HardGamePlay();.
4

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

2 Comments

When I try to add your last code block to public interface GamePlay, it gives me two errors: Variable 'gamePlayMode' might not have been initialized and Interface methods cannot have body. What am I doing wrong?
For your first point, I forgot to initialize the variable gamePlayMode to null (answer edited). An interface cannot contain code, it is just used to declared your methods. The code will be written in the classes that implements the interface, i.e. in HardGamePlay and in EasyGamePlay.
3

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();
    }

}

Comments

2

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.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.