4
votes

How to define a trait with an abstract method that need to be present even tho it can have different arguments. I just want to make sure the class that extends the trait has the method and the same return type. The example bellow (mainly illustrative) overloads the "add" and gives an error that "add" needs to be defined. How should I change the method declaration in the Trait?

Unfortunately all the answers don't work. I am not sure if I was clear, but I don't want to have any defined types in the arguments to be defined/checked (Any, generic, type definition) as the type of it and number of arguments can change, in my case the return could be the same. I just want it to check if a method with the same name and return is present ignoring the arguments. "Any" is not an alternative as it is not typesafe and I want to define clearly what the functions expect as arguments.

Example:

trait X{
  def add: Boolean
}

class Y extends X {
  def add(i: Int, s: String) : Boolean = {...}
}

class W extends X {
  def add(i: Int, y: Int, w: Set[String]) : Boolean = {...}
}
2
How would a user of X be able to call these methods?Lee
X it would be working as an abstract. So it would just define and be extended.Trp

2 Answers

5
votes

An explanation of the problem

In Scala the methods/functions def method(x: Int) : Boolean def method() : Boolean def method() : String are different.

By chance they have the same name, but for this semantic connection the Scala compiler does not care. So as you only would describe the return type but not the arguments of the function you would not supply enough information to the compiler for the definition of a trait. An option could be to give the most generic type Any and any number of arguments. An matching just based on the function name would by normal means not be possible. One could use reflection for this but this would pretty likely end up in a hack with a lot of expensive overhead.

Here are some possible solutions using standard language features:

Any number of arguments any kind of input

// any count and any type of input allowed, not much type safety
trait XAny{
  def add(args : Any*): Boolean
}

Any number of arguments input type given by type parameter

// any count and any type of input allowed, all input has to be a kind of A
trait XWithType[A]{
  def add(args : A*): Boolean
}

Alternate solution with method that has no restrictions given

// any count and any type of input allowed, all input has to be a kind of A
trait XWithArbitraryMethod{
  def add(): Boolean // here add now would call the real implementation
}
1
votes

How about something like this?

trait X{
   def add(as: Int*): Boolean
} 

That would work for all of your named cases by using varargs. However this won't work if you want to pass parameters of different types, but will work with any number of Int arguments.

See this question

If you want to be super dynamic and don't care about typesafety you could also change the parameter type to Any*, but there's probably a better way to do that which doesn't sacrifice typesafety.