0

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:

  • java: java version "1.8.0_144"
  • javac: javac 1.8.0_144
  • scala: Scala code runner version 2.12.3
  • scalac: Scala compiler version 2.12.3
  • OS: Darwin ***.local 17.0.0 Darwin Kernel Version 17.0.0: Thu Aug 24 21:48:19 PDT 2017; root:xnu-4570.1.46~2/RELEASE_X86_64 x86_64

Update:

For anyone who is interested in resolution of this:

Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
  • I don't think companionship plays any role here – Eduardo Pareja Tobes Oct 03 '17 at 15:27
  • @EduardoParejaTobes you mean there is no need in companionship, yes? – Andrii Abramov Oct 03 '17 at 17:51
  • yup, that this is similar to https://stackoverflow.com/q/32203867/614394 but for values. I think it's fine for types, and wrong for values :) – Eduardo Pareja Tobes Oct 04 '17 at 11:36
  • There is some sense in such kind companions. For example: `scala.util.Random`. Or when you have DTO that returns static data, e.g. description of service, terms of use, etc. – Andrii Abramov Oct 04 '17 at 12:40
  • I meant not about companions extending the class/trait they accompany, but about an object having "access to itself" when extending any other class/trait. I think its type should be accessible (so that you can write `object X extends Y[X.type]`), but its values not. – Eduardo Pareja Tobes Oct 04 '17 at 16:49

3 Answers3

2

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).

som-snytt
  • 39,429
  • 2
  • 47
  • 129
1

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.

Oleg Pyzhcov
  • 7,323
  • 1
  • 18
  • 30
  • Thank you for answering. So what is the resolution of my question? Is it a bug? Edge case? – Andrii Abramov Oct 03 '17 at 17:51
  • @AndriiAbramov I don't know. I'd call a bug that by-name parameter isn't working while the message suggests that it should (esp. if older versions of Scala supported that, which I cannot check now), but it's probably enough of an edge case too, since nobody seemed to care for at least since 2.10. – Oleg Pyzhcov Oct 03 '17 at 18:28
0

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.

Eduardo Pareja Tobes
  • 3,060
  • 1
  • 18
  • 19