Lisa Anne
Lisa Anne

Reputation: 4595

How to call method of the subclass?

I have a superclass like this:

public class GenericUpdate{

//...other stuff...

public String getName(){return null;};

}

And a subclasses like this:

public class FromFriend extends GenericUpdate {

@Override
public String getName() {return getFriend().getName();}

}

or this:

public class FromArtist extends GenericUpdate {

@Override
public String getName() {return getArtist().getName();}

}

Now,

some other class delivers me a list of GenericUpdate

if I iterate on the list and call GenericUpdate.getName() I get null back from getName()

is there a nice solution to avoid this?

Thanks


EDIT EDIT EDIT EDIT EDIT

the actual instances of the GenericUpdate class are retrieved from Android Intents, they are retrieved like this:

    genericUpdate=intent.getParcelableExtra(GENERIC_UPDATE);

and they are put in the intent like this:

GenericUpdate genericUpdate=((FlowAdapter)parent.getAdapter()).getItem(position);    
//...                        
intent.putExtra(PostDetailActivity.GENERIC_UPDATE,genericUpdate);
//...

Upvotes: 1

Views: 92

Answers (3)

aioobe
aioobe

Reputation: 420991

All methods in Java are virtual, so you can't "accidentally" call the base class method on an object of a subclass.

To see the runtime type of the objects in your list, you can for instance print genericUpdate.getClass().toString().

If this gives class com.mypackage.javaclasses.FromFriend then getFriend.getName() most likely return null. If this gives class com.mypackage.javaclasses.GenericUpdate your objects are not of the right subtypes and there should be no surprise that the subclass implementations of getName are not called.

(Turns out it was the latter in this case.)

So if you have control over the code of the GenericUpdate class you can make sure this situation is avoided by making GenericUpdate abstract. (Note that an abstract class can still have fields.)

Upvotes: 2

Patrick W
Patrick W

Reputation: 1567

From your statement above, the class GenericUpdate has a method getName() which returns null. If you observe correctly, this class can also be instantiated. Therefore, if you have a list of GenericUpdate classes, they will always return null, since the getName() method always returns null.

If you don't want your Generic class to be instantiated, you can do something like this:

public abstract class GenericUpdate{
    public abstract String getName();
}

Then, you can now extend your classes the same way you've done. Now, to use the GenericUpdate's getName() method, you have to do something like:

GenericUpdate fromFriend = new FromFriend();
fromFriend.getName();

This will never return null for GenericUpdate as long as the getFriend().getName(); method in your implementation has a value, and is not null.

Another alternative is to use Krzysztof Cichocki answer above.

Upvotes: 2

Krzysztof Cichocki
Krzysztof Cichocki

Reputation: 6414

Maybe you need interface?

public interface GenericUpdate{

//...other stuff...

public String getName();

}

public class FromFriend implements GenericUpdate {

@Override
public String getName() {return getFriend().getName();}

}

or this:

public class FromArtist implements GenericUpdate {

@Override
public String getName() {return getArtist().getName();}

}

Then no one could add a non valid object to your list, and there should be always a valid implementation of this method if you have an instance of object implementing this interface.

The interfaces role is exactly that, to tell others what they should implement, so you can have some abstact algorithm that uses this kind of objects that implement it.

You can't instantiate pure intercface, you need to implement it, and this guarantess you, that every object will have implementation, that should be valid.

Upvotes: 2

Related Questions