1

I'm creating a Mario clone where everything on the screen is an instance of ScreenElement. A ScreenElement is Landable if it can be landed on by Mario.

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

Some classes override isLandable, for example:

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. That is to say, I need polymorphism. Now this all works fine as long as isLandable is an instance method. However whether or not a given ScreenElement is Landable depends on the class, not the instance. So isLandable should really be static. 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. 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.

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; } 
7
  • Why not make a LandableElement class that inherits ScreenElement and is inherited by landable elements? Then you can override the method in Landable Element or alternatively just use instanceof LandableElement to check if objects are landable. Commented Jan 17, 2016 at 6:19
  • @Zar, instanceof is probably not the best advice; in general or otherwise. Commented Jan 17, 2016 at 6:26
  • @Zar In some cases, I have a sub class override isLandable a second time to set it back to false. Commented Jan 17, 2016 at 6:30
  • @ChiefTwoPencils What's so bad about using instanceof? Commented Jan 17, 2016 at 7:00
  • If your code is checking if an object is an instanceof this or that, there's, with little exception, a better design. One that will improve your code and life. Commented Jan 17, 2016 at 7:06

2 Answers 2

1

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. By creating a new class that is a ScreenElement, if they wish to change this behavior, they must override that method to do so.

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.


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.

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.

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.

private ScreenElement getGenericScreenElement(Mario mario) { for (ScreenElement element : screenElements) { if (element.isLandable()) { //return element if it matches additional criteria } } return null; } 
Sign up to request clarification or add additional context in comments.

11 Comments

Yes your right, and it is working correctly now. However, I have encountered another problem which is why I'm bringing this up. Check out the edit I made to my question.
@Amaar: I've revised my answer. You're still overthinking this.
So your suggesting that I leave it as an instance method, and create an instance if I need to figure out if a particular class is Landable.
@Amaar: I would presume that you already have an instance at this point. Otherwise, how would you be interacting with it?
With an object of type Class<? extends ScreenElement>.
|
0

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.

So make the methods instance methods without using the instance state.

1 Comment

I see your point. In fact that is how I have it set up right now. The thing is, I have encountered a case where I have a given class and need to use the isLandable method. The only way that I can get this done is by creating an instance of the class just to be able to call this method, which seems unnatural.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.