0

I've two traits:

trait Repository[T] {
  def insert(obj: T): Task[T]
}

trait RoleRepository extends Repository[Role]

And then I've added implementation for RoleRepository:

class RoleRepositoryImplem(val db: Db) extends RoleRepository {
    def insert(role: Role): Task[Role] = {
      //some implementation here
    }

In my implementation I've made a mistake (as I thought): I've named parameter as "role" and not "obj". But project actually compiled and run just fine. It's looking strange to me and I think this can lead to a lot of confusion if someone will write own code depending on trait Repository. I'm using Scala 2.12.2 in my project. Can some one shade light on this issue? Why this happened and how this can be fixed?

3 Answers 3

2

The parameters to the methods are only the names for the type it accepts.

say you have a method addNumber(number: T) and when you override the method, you have to follow the same signature but you can give the argument a better name which makes more sense in that context, for example addNumber(integer: Integer).

Take an example of Bag which contains items(item is a generic term here)

  trait Bag[T] {
    def addToBag(item: T)
    def items(): List[T]
  }

If the bag contains fruits, you will add fruit to it, so it makes more sense to call the input argument as fruit: Fruit but its up to you to call it whatever you want.

  case class Fruit(name: String)
  trait FruitBag extends Bag[Fruit]


  class MyFruitBag extends FruitBag {
    var list = scala.collection.mutable.ListBuffer[Fruit]()

    override def addToBag(fruit: Fruit): Unit = {
      println("adding item")
      list.+=:(fruit)
    }

    override def items(): List[Fruit] = list.toList
  }

If the bag contains Toys, you will want to call the input argument as toy which is more contextual but again you can give it whatever name you want.

  case class Toy(name: String)
  trait ToyBag extends Bag[Toy]
  class MyToysBag extends ToyBag {
    var list = scala.collection.mutable.ListBuffer[Toy]()

    override def addToBag(toy: Toy): Unit = {
      println("adding item")
      list.+=:(toy)
    }

    override def items(): List[Toy] = list.toList
  }

Summary is when you override methods you override the signature only, not necessarily the exact names of the arguments, arguments are named based on the context of the child class.

Sign up to request clarification or add additional context in comments.

Comments

2

The name you use depends on the type known by the compiler at the time of the call, not the real name of the implementation.

for instance :

val repo: RoleRepositoryImplem = new RoleRepositoryImplem(db) 
repo.insert(role = foobar) // this works
val repoAsTrait: Repository[Role] = repo 
repoAsTrait.insert(obj = foobar) // role name no longer works

I don't find it really confusing : when you only know that you have a Repository, then you use a more generic name obj, otherwise role if you know the precise type at the time of the call.

Side note :

Keep in mind that when scala is compiled to bytecode the name of the parameter is lost, as bytecode does not handle named parameter. So there is no way at runtime to know what is the real name of the parameter (excluding slooooow introspection). The scala compiler just translates the name to a position in the parameters.

Comments

1

Name of overridden/implemented method parameters don't need to be the same in superclass/trait and in subclass. It is true in Scala and in many more languages. It's quite typical for an OO language to not require the same parameter names in mentioned situation.

3 Comments

"So after you compile your class/trait, the parameter names are lost. You can store parameter names in class file by using -parameters compiler argument, but it's not a default behavior." This is wrong: Scala does store the parameter names in any case (not in the way Java understands), and -parameters is only for Java compiler.
Scala also compiles like -parameters does.
@AlexeyRomanov Yep.. you are right - I've removed this paragraph.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.