0

I was trying to answer another SO question which led me to me asking my own one. I did some research but could not find any information on the above topic.

I have an abstract class Character which has 1 abstract method defined below with varargs parameter

public abstract class Character {
   public abstract void doSomething(int... values);
}

I was under the impression that any class that extends this class could override this method with any number of parameters.

// 1st example
public class Player extends Character { 
   @Override
   public void doSomething(int x, int y) { // Two params - do something }
}

// 2nd example 
public class NPC extends Character {
   @Override
   public void doSomething() { // No params - do something }
}

But both the above examples resulted in a compile time error. I wanted to know what am I missing here? Is the above mentioned scenario even possible?

Any help is appreciated.

Nicholas K
  • 15,148
  • 7
  • 31
  • 57

3 Answers3

5

Variable argument functions in Java is a pure compiler trick: when you declare a method like this

public abstract void doSomething(int... values);

the compiler creates a method like this

public abstract void doSomething(int[] values);

and makes a "mental note" for itself to let you call doSomething with any number of integer parameters as you wish. When you make a call, the compiler wraps the parameters that you list to an array, and passes that array to an implementation of doSomething.

As for an ability to override such method with an implementation taking a fixed number of parameters, this would be impossible: if Java were to allow it (which it does not), programmers would be able to create class hierarchies that violate the interface of abstract classes that they extend. In your first case, Player would not be able to handle this call:

Character player = new Player(); // Allowed
player.doSomething(1, 2, 3, 4, 5); // What happens to 3, 4, and 5?
player.doSomething(1); // What value do we pass for y?

NPC would have the same problems, too.

You can override variable-argument method with a method taking an array:

@Override
void doSomething(int[] values) {
    ...
}

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • @NicholasK Absolutely - you can override it with `void doSomething(int[] values);` – Sergey Kalinichenko Aug 23 '18 at 18:13
  • And also, It doesn't really help if I make the method abstract with `varargs` correct? Because in the end I'm not really achieving anything if finally it has to be overridden by an array of type int. – Nicholas K Aug 23 '18 at 18:21
  • @NicholasK Making it vararg in the abstract class is useful, because it lets the callers to invoke the method with variable number of arguments when calling through a variable typed as abstract class, i.e. `Character player = new Player()` instead of `Player player = new Player()`. – Sergey Kalinichenko Aug 23 '18 at 18:27
  • @NicholasK Check out the demo link. Click "fork" at the top, then replace `Character.doSomething` method with `abstract void doSomething(int[] x);` Click [Run] and see what is going to happen ([you are going to get a compile error](https://ideone.com/kxPjqD)). This is because using `int...` in the signature of the base class enables vararg calls to derived class as well. – Sergey Kalinichenko Aug 23 '18 at 18:37
2

It is because you are overloading the method, not overriding. To override, you need to have the exact same parameters, here varargs -> int... or array -> int[].

You can see the difference between both here : https://stackoverflow.com/a/2469860/8923905

Emmanuel H
  • 82
  • 8
-1

I think you have the concept of abstract methods all wrong. When a class subclasses an another abstract class, it should provide a concrete implementation of the base class's abstract methods.

Thus when you declare a method like:

abstract void doSomething(int someInt);

The subclassing class, must provide a concrete implementation for a method with the same signature. Anything other than that is considered an invalid method declaration that results in the compilation error you're seeing.

I think you should better have a look at the documentation explaining the proper usage of abstract classes and methods.

https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

akortex
  • 5,067
  • 2
  • 25
  • 57
  • The confusion here was not on abstract classes and interfaces. It was on an abstract method that has varargs parameters. – Nicholas K Aug 23 '18 at 18:20