0

I am trying to understand inheritance from the Head First Java book. On page 193 I got everything right, and I am trying to invoke a method with a different parameter ( an overloaded method ), but the main class invokes the one inherited from the superclass. How can I invoke the following method?

boolean frighten(byte b) {
    System.out.println("a bite?");
    return true;
}

I tried to declare a byte, but it did not help. Thank you guys, here are the codes:

public class MonsterT {
    public static void main(String[] args) {
        Monster[] ma = new Monster[3];
        ma[0] = new Vampire();
        ma[1] = new Dragon();
        ma[2] = new Monster();
        for (int x=0; x < 3; x++) {
            ma[x].frighten(x);
        }

        byte y = 2;

        ma[0].frighten(y);
    }
}

class Monster {
    boolean frighten(int z) {
        System.out.println("arrrgh");
        return true;
    }
}

class Vampire extends Monster {
    boolean frighten(byte b) {
        System.out.println("a bite?");
        return true;
    }


class Dragon extends Monster {
    boolean frighten(int degree) {
        System.out.println("breath fire");
        return true;
    }

And the output is: arrrgh breath fire arrrgh arrrgh

Dávid Katona
  • 47
  • 1
  • 10

3 Answers3

0

You can do that by casting ma[0] to Vampire: ((Vampire)(ma[0])).frighten(y);

Why it does not work currently?

You can't do that with current structure of classes and methods because of Method Invocation Conversion, applied when you invoke frighten() on Vampire object with byte argument:

Method invocation contexts allow the use of one of the following:

  • an identity conversion (§5.1.1)

  • a widening primitive conversion (§5.1.2)

  • a widening reference conversion (§5.1.5)

  • a boxing conversion (§5.1.7) optionally followed by widening reference conversion

  • an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.

Specifically, what happens in your case, is a widening primitive conversion:

  • byte to short, int, long, float, or double

(in your case: from byte to int)

syntagma
  • 23,346
  • 16
  • 78
  • 134
0

Try this, casting down Monster to vampire , because the object at ma[0] is a Vampire referenced by Monster.

((Vampire)ma[0]).frighten(y);
The Scientific Method
  • 2,374
  • 2
  • 14
  • 25
0

The point here is the difference between overloading and overriding - see this answer for more.

So your class tree looks as follows:

 Monster
|       |
Vamire  Dragon

This means that the

frighten(int z)

method is availble by inheritance to all three classes and could be overloaded (= same types - as it has been in the Dragon class).

While the

boolean frighten(byte b) 

Is an overriding (not the same type of parameter), so that you could call

frighten(byte) 
   and 
frighten(int) 

on your Vampire.

Another aspect that comes into play is object type casting.

So at the end all your objects are "Monsters in the monster array "ma" - and will be seen as monsters.

This will be changed to vampire by the cast that @The Scientific Method demonstrated in it's answer.

Without the cast the byte would be auto type casted to int.

PowerStat
  • 3,757
  • 8
  • 32
  • 57
  • That's what i thought too, but i didn't understand why 'byte y = 2; ma[0].frighten(y);' didn't work, despite that i gave it a byte argument. – Dávid Katona Oct 12 '18 at 12:00
  • That's because "Monster[] ma" so all your objects are in a monster array - and will be seen as monsters. This will be changed to vampire by the cast that @The Scientific Method demonstrated in it's answer. Without the cast the byte would be auto type casted to int. – PowerStat Oct 12 '18 at 12:04
  • Added this explanation to the main answer. – PowerStat Oct 12 '18 at 12:10