1

I Have something similar to this setup:

public class Base {
    public String getApple() {return "base apple"};
}

public class Extended extends Base{
    public String getApple() {return "extended apple"};
}

Somewhere else in the code I have this:

{
    Base b = info.getForm();

    if (b instanceof Extended){
        b = (Extended) b;
    }

    System.out.println(b.getApple()); // returns "base apple" even when if clause is true why??

}

How do I accomplish that?

3
  • Do you want to return base apple every time or is it returning base apple every time and you don't know why> Commented Jul 28, 2009 at 19:31
  • You should post a minimal code example that compiles and reproduces the problem when executed. If you do that, you probably will already yourself notice what the problem is. Commented Jul 28, 2009 at 20:06
  • Thx for the answers guys, this place is really amazing! My java code was actually fine... the one above was just for illustration but I will make an effort next time to post code that actually compiles. The problem was actually in the javascript that was making the ajax request, I failed to serialize the form before submitting the request... anyways I really learned quite a lot from all the answers! :) Commented Jul 28, 2009 at 21:04

8 Answers 8

6

First:

if (b instanceof Extended){
    b = (Extended) b;
}

does absolutely nothing. You are basically saying b = b, which says nothing. You are not even changing the reference.

Second, getApple() will always be dynamically bound, and the "extended apple" should always be called - given that the subclass is truly extending the base class, and the method is truly overridden.

Basically what you need to do, in order to accomplish correct getApple() behavior:

  • remove the if clause. it does nothing.
  • make sure your class is indeed extending the base class
  • make sure the getApple() method is overriding the base class method. (use the @override annotation if you are not sure)
Sign up to request clarification or add additional context in comments.

3 Comments

I assume he is using it to determine absolutely that his b really is an Extended.
But it still changes nothing... The if clause has no effect whatsoever.
The if clause does nothing, in java "casts" just make sure that the cast is allowed, they don't actually do a "cast", unlike C for example.
4

As written, your code will not compile, which makes me think that your problem is elsewhere. Your return statements don't have semicolons at the end of them. Rather, they appear after the }. It's possible you had some other problem (maybe your subclass misspelled getApple()), but you're still using your old class files because your new stuff isn't compiling.

This code works:

class Base {
   public String getApple() { return "base apple"; }
}
class Extended extends Base {
  public String getApple() { return "extended apple"; }
}
public class Test {
  public static void main(String[] args) {
     Base b = new Extended();
     System.out.println(b.getApple());
  }
}

Console:

#javac Test.java
#java Test
extended apple

2 Comments

As a side note, this works because all methods in Java are virtual.
From a C++ perspective, that is correct. More precisely, all method calls in Java are dynamically bound at runtime.
1

First of all, that if block should never be necessary. It's basically a no-op.

Second, this isn't your real code, because it doesn't even compile. You're missing semicolons after the return statements.

I suspect that your problem is that your real code has a typo that's making the signatures of the two getApple methods different. This means that Extended has two methods: the one inherited from Base and the one with a different signature in itself. Since you're calling with the signature of the Base.getApple method, you're always getting that behavior. This is only a guess though, as your posted code does not exhibit the problem you describe.

Comments

1

Yuval is right that your cast in the if block has no effect. You might try combining your last statement with the if:

if (b instanceof Extended)
{
    // Prints "extended apple" if reached.
    System.out.println(((Extended)b).getApple()); 
}

2 Comments

totally unnecessary. "extended apple" will be printed even if you do not cast to (Extended).
I guess the behavior he reported in his code comment is the result of something else then?
1

Add @Override to the method in your subclass and recompile. This will help you find out if you're not actually overriding the method you think you are.

i.e.

public class Base {
    public String getApple() {return "base apple";}
}

public class Extended extends Base{
    @Override
    public String getApple() {return "extended apple";}
}

Comments

0

The only way to get that behavior is to return super.getApple() in your extended class, which is effectively the same as not overriding it in the first place. The only way this could help is if you pass in an argument to decide which to return. Not saying thats good design...

Forgot to mention that, as Yuval said, the cast does nothing to the object.

Comments

0

You should investigate what is constructing your instance that is returned from info.getForm(). You may want to make the Base abstract to prevent it from being instantiated and you'll quickly see where construction is happening.

Comments

0

Are you sure your code example provided in your question EXACTLY matches the code your are using? The reason I ask is that the behavior you are describing happens when you access a public FIELD instead of a public METHOD with an object pointer.

For example:

public class BaseClass {
    public String baseField;

    public BaseClass() {
        baseField = "base";
    }

    public String getBaseField() {
        return baseField;
    }
}

public class SubClass extends BaseClass {
    public String baseField;

    public SubClass () {
        baseField = "sub";
    }

    public String getBaseField() {
        return baseField;
    }
}

public class MainClass {
    public static void main(String[] args) {
        BaseClass baseObject = new BaseClass();
        SubClass subObject = new SubClass();
        System.out.println(baseObject.getBaseField());
        System.out.println(subObject.getBaseField());
        System.out.println(baseObject.baseField);
        System.out.println(subObject.baseField);
        System.out.println(((BaseClass)subObect).getBaseField());
        System.out.println(((BaseClass)subObect).baseField);
    }
}

Will print out:

base
sub
base
sub
sub
base

When you call a method, the JVM will start at the bottom of the inheritance hierarchy and call the appropriate method. When you reference a field instead, it uses the class of the pointer instead of walking up the class hierarchy to resolve the value. The behavior of the field reference matches what you're seeing, which is why I ask for clarification/verification.

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.