Andrii Abramov
Andrii Abramov

Reputation: 10773

Scala class singleton with non-default constructor parameters

I have already read about issues with objects inheriting from companion classes.

For example:

But I have a bit different issue (I am not sure that it is a bug)

I have the following code:

class Scala(name: String)

import Scala._

object Scala extends Scala(TEST_NAME){
  val TEST_NAME = "test name"
}

Note, that I am using variable defined in scope of companion object and then passing it to super's constructor.

I am getting the following compilation error:

Scala.scala:5: error: super constructor cannot be passed a self reference 
unless parameter is declared by-name

object Scala extends Scala(TEST_NAME){
                           ^
one error found

Other variants that I have tried:

Call by name:

class Scala(name: => String)

import Scala._

object Scala extends Scala(TEST_NAME){
  val TEST_NAME = "test name"
}

Named argument:

class Scala(name: String)

import Scala._

object Scala extends Scala(name = TEST_NAME){
  val TEST_NAME = "test name"
}

Both of them:

class Scala(name: => String)

import Scala._

object Scala extends Scala(name = TEST_NAME){
  val TEST_NAME = "test name"
}

Some environment details:

Update:

For anyone who is interested in resolution of this:

Upvotes: 0

Views: 1776

Answers (3)

som-snytt
som-snytt

Reputation: 39587

For your restricted use case:

scala> class C(s: String) ; object X extends C(X.x) { final val x = "hello, world" }
defined class C
defined object X

The constant value definition is inlined (per the spec).

Upvotes: 2

Oleg Pyzhcov
Oleg Pyzhcov

Reputation: 7353

You can use an obscure feature that is going to be removed in Scala 3: early initializers. It allows you to specify init code to run before you call superclass constructor.

class Scala(name: String)

object Scala extends {
  val TEST_NAME: String = "test name"
} with Scala(TEST_NAME) { /* rest of object code */ }

Note that import is not required - TEST_NAME is already in the scope.


Here's a Scastie snippet to prove that it works.

Upvotes: 1

Eduardo Pareja Tobes
Eduardo Pareja Tobes

Reputation: 3120

If your code above would compile then you could write

class A(val x: String)

object B extends A(B.x_again) {

  val x_again = x
}

which certainly doesn't look good.

Upvotes: 0

Related Questions