Objects and traits with the same name

This code throws out a warning but seems to work fine in sbt. My question is - is this a problem? I saw an example in other code of objects extending traits with the same name - or is this not best practice?

trait A {
  def hello() = println("hello")
}

object A extends A {
  def main(args: Array[String]): Unit = hello()
}

A has a valid main method (args: Array[String])Unit,
[warn]   but A will not have an entry point on the JVM.
[warn]   Reason: companion is a trait, which means no static forwarder can be generated.

https://stackoverflow.com/questions/49737453/scala-object-and-trait-having-same-name

The above says that an object doesn’t extend a trait but accompanies it (similar to a class) but then shouldn’t another keyword be better than ‘extends’? Also, isn’t the companion referred to in the warning above, the object, not the trait?

Note that the StackOverflow answer doesn’t include the extends keyword. In your example, you have a companion object which also extends the trait.

I think that the answer to your question goes into how Scala compiles object declarations and what the JVM needs to run a program. I expect that your trait here gets compiled into a Java interface and you can’t put an entry point in an interface. Prior to Java 8 you couldn’t have static methods at all in interfaces. If you look a the .class files generated by compiling Scala objects, they get a mangled name with a $ to distinguish them from the companion. When that companion is a class, the Scala compiler can put an entry point as a static method in the class which is what you run. It calls the appropriate code in the companion object.

Unfortunately, I haven’t played with all the details of interfaces added since Java 8, but I’m guessing that while you can put static methods in them, you can’t make a main that is an entry point for the program. You said that this works fine in sbt. Do you fork the run process? If not, I can imagine sbt being able to call this when it wouldn’t be runnable on its own because if you don’t fork, the program runs in the same JVM instance as sbt.

Sorry so much of that is speculation and I don’t have an exact answer.

2 Likes