简体   繁体   English

动态比较java中的类型

[英]Dynamically compare types in java

I have a Screen class, which is the base class of several kind of screens, eg PauseScreen, MainScreen, etc. 我有一个Screen类,它是几种屏幕的基类,例如PauseScreen,MainScreen等。

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. 假设我有一个主屏幕,一个GameScreen和一个PauseScreen。 I need to go from PauseScreen to MainScreen, ( popping PauseScreen and GameScreen ). 我需要从PauseScreen转到MainScreen,(弹出PauseScreen和GameScreen)。

What is the prefered way to do it in java? 在java中首选的方法是什么? I could store an id in each screens but it doesn't seems right. 我可以在每个屏幕上存储一个id,但似乎不对。

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? ). 编辑:这就是我想要实现的目标,我只是想知道是否有更好的方法不需要创建枚举(IIRC可以在运行时获取类的类型,但也许它是一个坏的练习我想做什么?)。

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 使用instanceof运算符

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: 您可以将instanceof运算符用于此类目的:

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 本教程中有关于此主题的部分: 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. 访问者使用双重调度机制来允许类型安全的向下转换,而无需使用instanceof和cast。 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. 虽然在特定情况下与使用instanceof没有太大区别,但它是一个非常灵活的模式 - 允许许多不同类型的Visitor实现 - 并且它通过编译时错误突出显示使用,因此当您创建Screen的新实现时,您可以扩展访问者界面并快速查找需要更新的所有位置以处理访问新类型的屏幕。

You can directly refer to classes using the .class operator, which returns a java.lang.Class instance: 您可以使用.class运算符直接引用类,该运算符返回一个java.lang.Class实例:

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). 请注意,可以使用引用相等( ==!= )而不是对象相等( equals方法)来比较java.lang.Class实例。 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: 如果要检查是否extendsimplements它,可以使用java.lang.Class#isInstance(Object)方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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