简体   繁体   中英

Dynamically compare types in java

I have a Screen class, which is the base class of several kind of screens, eg PauseScreen, MainScreen, etc.

I have a stack of screens in my classes, and my game is pushing / poping screens depending on the buttons.

But I need to jump from one screen to another ( popping everything until the needed screen ).

Lets say I have a MainScreen, a GameScreen and a PauseScreen. I need to go from PauseScreen to MainScreen, ( popping PauseScreen and GameScreen ).

What is the prefered way to do it in java? I could store an id in each screens but it doesn't seems right.

Edit : This is what I want to achieve, I was just curious to know is there was a better way that would not require creating an enum ( IIRC it is possible to get the type of the class at runtime, but maybe it is a bad practice for what I want to do? ).

class X
{
    Stack< Screen > screens = new Stack< Screen >();

    void push( Screen s )
    {
        screens.push( s );
    }

    void pop()
    {
        screens.pop();
    }

    void popUntil( Screen.Type t )
    {
        // go through the list in reverse order
        while( screens.next().type != t )
            screens.pop();
    }
}

// other places in the code

app.popUntil( Screen.Type.MainScreen );
app.popUntil( Screen.Type.GameScreen );

Use the instanceof operator

Screen screen = stack.pop();
if (screen instanceof PauseScreen) {

}
else if (screen instanceof MainScreen) {

}
else if (screen instanceof GameScreen) {

}
else if (/*...*/) {
    //...
}
else {
    otherStack.push(screen);
}

You can use the instanceof operator for this kind of purpose:

if(someObject instanceof SomeType)
{
    SomeType cast = (SomeType) someObject;
    //do stuff with cast
}

There's a section in this tutorial about this topic: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html

This could be a good candidate for the Visitor pattern .

public interface ScreenVisitor {
    void visitMain(MainScreen screen);
    void visitGame(GameScreen screen);
    void visitPause(PauseScreen screen);
}

public class VisitorForStuff implements ScreenVisitor {
    void visitMain(MainScreen screen) {
        // do stuff for MainScreen
     }
     // etc.
}

public abstract class Screen {
    ...
    public abstract void visit(ScreenVisitor visitor);
    ...
}

public class GameScreen extends Screen {       
    ...
    public void visit(ScreenVisitor visitor) {
        visitor.visitGame(this);
    }
    ...
}

...
Screen screen = stack.pop()
screen.visit(new VisitorForStuff());
...

The Visitor uses a double-dispatch mechanism to allow for type-safe downcasting without the use of instanceof and casting. Although there's not a huge difference from using instanceof in a particular case, it's quite a flexible pattern - allowing for many different types of Visitor implementations - and it cane highlights uses through compile-time errors, so when you create a new implementation of Screen, you can extend the Visitor interface and quickly find all the places which will need to be updated to handle visiting the new type of Screen.

You can directly refer to classes using the .class operator, which returns a java.lang.Class instance:

class X
{
    // ...

    void popUntil(Class<? extends Screen.Type> type)
    {
        // go through the list in reverse order
        while( screens.next().getClass() != type)
        {
            screens.pop();
        }
    }
}

x.popUntil(Screen.Type.MainScreen.class);
x.popUntil(Screen.Type.GameScreen.class);

Note that instances of java.lang.Class can be compared using reference equality ( == and != ) rather than object equality ( equals method). However, this implementation checks only if the type of the instance is exactly the given argument. If you want to check if extends or implements it, you can use the java.lang.Class#isInstance(Object) method:

while (!type.isInstance(screens.next()))
{
    screens.pop();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM