简体   繁体   English

静态方法的多态

[英]Polymorphism with Static Methods

I'm creating a Mario clone where everything on the screen is an instance of ScreenElement . 我正在创建一个Mario克隆,其中屏幕上的所有内容都是ScreenElement一个实例。 A ScreenElement is Landable if it can be landed on by Mario. 如果ScreenElement可以由Mario登陆,则它是可登陆的。

public class ScreenElement {
    public boolean isLandable() {
        return false;
    }
}

Some classes override isLandable , for example: 一些类重写isLandable ,例如:

public class GrassBlock extends ScreenElement {
    @Override
    public boolean isLandable() {
        return true;
    }
}

And classes that don't override isLandable should inherit it from the closest super class that does. 并且不重写isLandable应该从最近的超类继承它。 That is to say, I need polymorphism. 也就是说,我需要多态性。 Now this all works fine as long as isLandable is an instance method. 现在,只要isLandable是实例方法,这一切都可以正常工作。 However whether or not a given ScreenElement is Landable depends on the class, not the instance. 但是,给定的ScreenElement是否为Landable取决于类,而不取决于实例。 So isLandable should really be static. 因此isLandable应该确实是静态的。 But if I make it static, I cannot override it or inherit in sub classes that don't explicitly define it. 但是,如果将其设为静态,则无法覆盖它或在未显式定义它的子类中继承。 Is there a simple workaround to this problem. 有没有解决此问题的简单方法。

EDIT: I do realize that the way I have it set up right now, it is working correctly but the reason I am bringing this up is because I have encountered a problem. 编辑:我确实意识到我现在设置它的方式,它可以正常工作,但是我提起它的原因是因为我遇到了问题。 Given a class that extends ScreenElement , I need to find out the result of isLandable . 给定一个扩展ScreenElement的类,我需要找出isLandable的结果。 The only thing I could think of was this: 我唯一想到的是:

private <S extends ScreenElement> boolean isThisLandable(Class<S> category) {
    return category.newInstance().isLandable();
}

I have to create a new instance to figure out something that doesn't depend on the instance, and this seems unnatural. 我必须创建一个新实例来找出不依赖于该实例的东西,这似乎是不自然的。

EDIT 2: Here's the specific piece of code that I'm dealing with. 编辑2:这是我正在处理的特定代码。

private <S extends ScreenElement> S getGenericScreenElement(Mario mario, Class<S> category) {
    for (ScreenElement element : screenElements) {
        if (category.isInstance(element)) {
            S elementToTest = category.cast(element);
            if (elementToTest.isLandable()) {
                //return elementToTest if it matches additional criteria
            }
        }
    }
    return null;
}

You're overthinking this. 您想得太多了。

In a nutshell, this code is doing exactly what you want it to do. 简而言之,此代码完全按照您想要的去做。

Here's what happens. 这是发生了什么。

Your parent class, ScreenElement , defines by the isLandable() method by default, and it is always set to return false . 默认情况下,您的父类ScreenElementisLandable()方法定义,并且始终设置为返回false By creating a new class that is a ScreenElement , if they wish to change this behavior, they must override that method to do so. 通过创建一个新的类ScreenElement ,如果他们希望更改此行为,则必须重写该方法。

The fact that your GrassBlock does override this method is indicative that any instance of a GrassBlock will register true if its isLandable() property is checked. GrassBlock 确实会覆盖此方法的事实表明,如果选中了isLandable()属性,则isLandable()任何实例 GrassBlock将注册true


With your code revision, you're still overthinking this. 在进行代码修订时,您仍然没有考虑这一点。

All you need to do when you attempt to use an instance of ScreenElement - be that an instance of ScreenElement or any of its children - is to just call the method . 当您尝试使用ScreenElement一个实例(即ScreenElement一个实例或其任何子级)时, 您需要做的就是仅调用该方法

You shouldn't care about that property until you decide to check it, during its run. 在您决定在运行期间决定对其进行检查之前,您无需关心该属性。 The way you're checking it now makes very little sense at all. 现在,您进行检查的方式几乎没有任何意义。

As an example: 举个例子:

ScreenElement vanillaElement = new ScreenElement();
GrassBlock block = new GrassBlock();

System.out.println(vanillaElement.isLandable()); // will print false
System.out.println(block.isLandable()); // will print true

More explicitly, with your sample code, you can greatly reduce it. 更明确地说,使用示例代码,可以大大减少它。 Many of your statements to check against the type are unnecessary, especially when casting. 您不需要检查许多类型的语句,尤其是在强制转换时。 You're guaranteed to have nothing more than a ScreenElement , and since isLandable() is defined on at least that, you will never run into a scenario in which you cannot call that method. 你保证有什么比一个 ScreenElement ,由于isLandable()是依据至少该定义的,你永远不会碰上,你不能调用该方法的情况。

The above will turn your code into this. 上面的代码将您的代码变成了这个。 I leave the addition of your Mario parameter up to you since its purpose is unclear in this method. 由于此方法的目的尚不清楚,因此我将剩下的Mario参数留给您。

private ScreenElement getGenericScreenElement(Mario mario) {
    for (ScreenElement element : screenElements) {
        if (element.isLandable()) {
            //return element if it matches additional criteria
        }
    }
    return null;
}

The fact that you need the methods to be overrideable and you want to do polymorphic dispatching means that they should not be static methods. 您需要方法是可重写的并且要执行多态调度这一事实意味着,它们不应为静态方法。

However whether or not a given ScreenElement is Landable depends on the class, not the instance. 但是,给定的ScreenElement是否为Landable取决于类,而不取决于实例。

So make the methods instance methods without using the instance state. 因此,使方法成为实例方法而不使用实例状态。

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

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