views:

214

answers:

6

Sorry if my question sounds weird lol I'll try to explain. I have 4 classes: Karakter, Karakters, Orc, Human. Orc and Human both extend Karakter. Karakters is an ArrayList with Karakter in it.

I have a method in both Orc and Human called: public String getRace(). Now I want to use this method in Karakters?!! When I try to do this, it fails because Orc and Human extend Karakter and not Karakters! Is there a way to do this? I heard something about making something abstract :P

Thanks

+1  A: 

To call getRace() defined in Orc or Human you need an object of Orc or Human or one of its derived classes (assuming the method is not private in base). Of course if getRace() is public static then you can use the class name to invoke it from anywhere.

Murali VP
+5  A: 

Declare the getRace() method in Karakter (note that the English spelling is "Character", but that's neither here nor there).

Since Karakters only knows that it's dealing with objects of type Karakter, it can't know that both implementations have a getRace method. Declaring the method in the base class solves this problem.

It should look like this:

public abstract String getRace();

And the Karakter class will also have to be made abstract.

Michael Myers
He's probably not using Character because of `java.lang.Character`.
Aaron Digulla
Thanks, mmyers. This is my answer :)
Nima
@Aaron: True, I forgot it was in `java.lang`.
Michael Myers
+3  A: 

What do you expect to happen when you call Karakters.getRace()?

Since Karakters is an ArrayList then why not just have a method getRace(int position) so that you can find the race of the person of interest.

I don't see how getting the race of an array makes any sense.

James Black
I don't expect anything to happen anything and I don't call Karakters.getRace(). I want to do this: arrayOfKarakters.get(i).getRace().equals("Human") or Orc! Thanks anyway :)
Nima
+2  A: 

This doesn't really make sense. If you have an ArrayList, then you can call getRace() on each element:

class Karakters {
    ArrayList<Karakter> kars = new ArrayList<Karakter> ();
    public String getRace () {
        for (Karakter k: kars) {
            ... uh ... which one to return?
        }
        return null; // List is empty
    }
}
Aaron Digulla
I want to look for each Karakter in the ArrayList and see if arrayL.get(i).getRace().equals("Human") or "Orc"
Nima
+1  A: 

You can test at runtime what is the concrete type of Karakter and cast to the appropriate SubType.

for(Karakter k : karakters) {
   if (k instanceof Orc) {
       ((Ork)k).getRace();
   } else if (k instanceof Human) {
       ((Human)k).getRace();
   }
}

Also, it looks like you could push up the method getRace() into Karakter, if it makes sense for a Karakter to have a getRace().

class/interface Karakter {
   abstract String getRace();
}

If it doesn't make sense for Karakter to have a getRace(), for instance, if there is another type Alien extends Karakter that doesn't have a getRace() you could abstract with an additional interface:

public interface IRacer {
    abstract String getRace();
}

public class Human extends Karakter implements IRacer { ... }
public class Orc extends Karakter implements IRacer { ... }

This way you could do:

for(Karakter k : karakters) {
   if (k instanceof IRacer) {
       ((IRacer)k).getRace();
   }
}

Also, it looks like your class Karakters extends ArrayList. Don't. Favor Composition over Inheritance and, always use the generic version of ArrayList<Karakter>.

bruno conde
no, Karakters doesn't extend ArrayList and I'm using ArrayList<Karakter> :) thanks.
Nima
+1  A: 

You can call the method on an object that implements that method, so long as it is accessible from your current class. In particular, since the getRace method is public, any class can call it so long as they have an appropriate instance of Orc or Human to call it on.

I expect that your sticking point is that you have a list of Karakters, rather than Orcs or Humans. Thus Karakters only knows at that point that the object is a Karakter, and so can only call methods defined in the Karakter class/interface.

One solution is to add the getRace method to the Karakter class as well. If it doesn't make sense for this to return a value in the superclass, then you can make the superclass abstract (which means you cannot construct an instance of it directly, you can only construct one of its subclasses), and declare the method abstract in Karakter too:

public abstract class Karakter
{
    /*
     ...
     ... Same as before
     ...
     */

     public abstract String getRace();
}

This forces the subclasses to have an implementation of getRace (which isn't a problem here, as they do anyway) and means that Karakters can now be sure that no matter what kind of Karakter object it has, there is a getRace() method to call.

This is just one approach to the solution based on what I understand your intent to be. But the underlying issue is that the Karakter class doesn't define getRace, and so the method cannot be called directly on references of that type.

Andrzej Doyle