Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala case class.type does not take parameters

Tags:

scala

I am a newbie to scala. Here is a Models.scala I am trying to write. When I run sbt package it is giving error

Models.scala:25: models.Session.Network.type does not take parameters
[error]         network : Network = Network() ,

I don't understand why this error is taking place, I am not passing any parameter in when doing Network(). Can someone please help me

like image 912
Anubhav Agarwal Avatar asked Nov 05 '14 21:11

Anubhav Agarwal


1 Answers

Here is a smaller code that reproduces your problem :

case class A(b:B = B(3, 5))

case class B(i: Int, j: Int)

object A {

  val B = "whatever"
}

On the first line, we get

too many arguments for method apply: (index: Int)Char in class StringOps    

What happens is that when you define the signature of the case class, you are both defining the signature of the constructor (when you call with new), and of the apply method in the companion object (when you call without new).

When you put default value in argument, (Network() in your code, and B(3, 5) in mine), this code will be compiled both in the context of the constructor and of the apply method of the companion object.

As you have defined a companion object Session, the apply method is automatically added into this object. It happens that Network() in your companion object means Network.apply() on the Network object you have defined there, and it means the string B with value "whatever" in my code.

What is really weird then is that it is possible that the default expression has different meanings, but both correct in the context of the constructor and of the apply method. In this case, you may get different behavior depending on whether you call with or without new.

Here is an example :

case class A(b:B = bb)

case class B(i: Int, j: Int)

object bb extends B(3, 4)

object A {

  val bb = new B(7, 2)
}


object Test extends App {

  println(A())
  println(new A())

}

Running test will print

A(B(7,2))
A(B(3,4))

For your specific problem, there are easy workarounds.

network: Network = models.Network(),

will work, obviously, because it is then clear that you want Network in the package and not in object Session.

network: Network = new Network(),

will work too, because with the new, the compiler will look for a Network type and not a Network value. In companion object session, the Network value is shadowed by the local declaration, but the Network type is not.

IMO, the former (models.Network) is clearer.


PS. I checked the specification and I believe this weird behavior is in line with it. Namely, (5.3.2) an apply method is genarated inside the companion object with the same parameter list as the constructor. That includes the default values, which would then be compiled inside the companion object.

like image 156
Didier Dupont Avatar answered Sep 18 '22 19:09

Didier Dupont