"Stable identifer required" error during companion object import - scala

I'm really new to Scala, and I've come across an error I am unable to solve by myself or through internet searches.
I have a Scala class called "GUI" that represents a JFrame along with a companion class. When I try to import the companion class using import GUI._ I get the error "stable identifier required, but GUI.this.GUI() found".
I made an empty class and companion object and the import worked fine, so I assume that the error is related to something specific to my code. Below is the code in question:
object GUI {
def test:Integer = 1
}
class GUI extends JFrame{
import GUI._
val ICON_LOCATION:File = new File("Images/iMovies.ico");
val ICON:BufferedImage = Ootil.createImage("iMovies.png");
val TITLE:String = "iVideos";
val LICENSE_NAME:String = "OpenBSD";
def GUI(){
setLayout(new BorderLayout());
createGUI();
pack();
setSize(100,100);
setLocationRelativeTo(null);
setVisible(true);
}
def versionMajor: Integer = 1
def versionMinor: Integer = 0
def versionRevision: Integer = 0
def versionPreReleaseID: String = "alpha"
def versionBuildNumber: String = "1b"
private def createGUI():Unit = {
val panel = new JPanel();
panel.setLayout(new BorderLayout());
add(panel, BorderLayout.CENTER);
}
def getIcon():BufferedImage = ICON
def getProgramTitle():String = TITLE
def getConfigOptions():LookAndFeelConfigurationOptions = GUIConfigOptions.CONFIG_OPTIONS;
}

To add to Kipton's answer, there's nothing wrong with doing:
class GUI{
def GUI() {
println("something")
}
}
But the result won't be a constructor -- it will be an ordinary method.
val a = new GUI() won't print anything, but calling a.GUI() will.
This is why you didn't get an error message about defining your constructor incorrectly.
When you run the command import GUI._, Scala needs GUI to always evaluate to the same object. This is only the case when GUI is an object, a package, or a val.
In your code, import GUI._ referred to the method GUI that you defined, because the GUI method is defined in a closer scope than object GUI (the fact that the compiler hasn't encountered the definition of def GUI yet doesn't make a difference).
Since import GUI._ referred to the method GUI, which is not a val, object, or package, you got the error message about GUI not being a stable identifier.

Welcome to the Scala community.
Scala constructors work differently than they do in Java. To fix the error, you should put the body of your previously defined GUI() method directly into the class definition, like so,
class GUI extends JFrame{
import GUI._
val ICON_LOCATION:File = new File("Images/iMovies.ico");
val ICON:BufferedImage = Ootil.createImage("iMovies.png");
val TITLE:String = "iVideos";
val LICENSE_NAME:String = "OpenBSD";
// ** stuff that used to be in method GUI() goes below **
setLayout(new BorderLayout());
createGUI();
pack();
setSize(100,100);
setLocationRelativeTo(null);
setVisible(true);
...
}
It takes a little getting used to, but I think you'll find that Scala's way is a lot nicer.
If you want to define an auxiliary constructor, declare a method def this(...) { ... } whose first expression is a call to the primary constructor (in this case just this(), since it doesn't take parameters).
If you want to add parameters to your primary constructor, you would define the class as
class GUI( << some parameters >> ) extends JFrame { ... }
and then you can use the parameters anywhere in this class body.

Related

Scala inner case class not serializable

I am trying to do a very basic serialization of a very simple case class in Scala:
import org.scalatest.wordspec.AnyWordSpecLike
import java.io.{ByteArrayOutputStream, ObjectOutputStream}
class PersistenceSpec extends AnyWordSpecLike{
case class TestClass(name: String) extends Serializable
def serializeSomething(): ByteArrayOutputStream = {
val testItem = TestClass("My Thing")
val bos: ByteArrayOutputStream = new ByteArrayOutputStream()
val oos = new ObjectOutputStream(bos)
oos.writeObject(testItem)
bos
}
"serializeSomething" when {
"executed" must {
"successfully serialize" in {
val outputStream = serializeSomething()
println(outputStream.toString())
}
}
}
}
When I run this test I get a java.io.NotSerializableException on the call to oos.writeObject(testItem), which makes no sense, since case classes automatically implement Serializable, and this is the simplest possible example.
However, if I paste the code for TestClass and serializeSomething() into repl, I am able to call the function, and it works just fine.
What is different when calling my function via scalatest, vs repl that would cause this exception?
One final note: If I change the call from oos.writeObject(testItem) to oos.writeObject("Hello"), it works fine, even when run from scalatest.
You need to define TestClass outside of PersistenceSpec.
Inner class instances automatically get a reference to the instance of the outer class. So, when you write it out, it tries to serialize the PersistenceSpec instance as well, and that of course fails.

Calling a method/function anytime a val/var is declared (without explicit method/function called)

Editing due to a combination of an overly complex example and not cleary stating my intentions.
I have a class that designers will extend from and build. To keep code clean I would like to be able to do a combination of actions when specific classes are instantiated.
I know that I can use a Companion Object with custom apply() to do most of this, and would work with the exception that I sort of need to know the class that is instantiating the specific class (and I'm trying to avoid passing this as a parameter).
class Apple{}
class Orange{}
class MyBase{
val allApples = ListBuffer[Apple]()
val allOranges = ListBuffer[Orange]()
}
//User defined classes extending MyBase
class SomeNewClass extends MyBase{
val apple1 = new Apple //we would want to add apple1 to the allApples List
val apple2 = new Apple
val orange1 = new Orange
}
class AnotherClass extends MyBase{
val someClass = new SomeNewClass
val apple1 = new Apple
}
So you can see that I want to be able to add the Apple instances to the allApples ListBuffer and same for the oranges. I'd like to be able to do this without requiring an addApple type of method. The problem is, I have no reference to SomeNewClass or AnotherClass (or whatever else the designer would make). I could have an implicit like the following:
class Apple()(implicit myBaseCaller : MyBase){
myBaseCaller.addApple(this)
}
class MyBase{
implicit val myself : MyBase = this
//excluded for clarity
}
Instantiating a new Apple or Orange outside of a class that extends MyBase would be a violation of the DSL in this particular case.
So I don't disagree that the best solution would be an explicit method to addApples, however I'm trying to see if there is a solution that is easier on the coding.
There may not be a decent way to do it, which would be ok. In this case I don't mind a little extra overhead in the base classes to make the extended classes easier to write.
Removed Original Question as too complicated
Instantiating a new Apple or Orange outside of a class that extends MyBase would be a violation of the DSL in this particular case.
It's not clear from the context whether that would be desirable or not.
In any case, have you considered what might be accomplished with a private constructor and a public auxiliary constructor?
import scala.collection.mutable.ListBuffer
class MyBase{
class Apple private (lb :ListBuffer[Apple]) {
lb += this
def this() = this(allApples)
}
class Orange private (lb :ListBuffer[Orange]) {
lb += this
def this() = this(allOranges)
}
val allApples = ListBuffer[Apple]()
val allOranges = ListBuffer[Orange]()
}
class SomeNewClass extends MyBase{
val apple1 = new Apple
val apple2 = new Apple
val orange1 = new Orange
}
class AnotherClass extends MyBase{
val someClass = new SomeNewClass
val apple1 = new Apple
}
val snc = new SomeNewClass
val ac = new AnotherClass
snc.allApples.size //res0: Int = 2
snc.allOranges.size //res1: Int = 1
ac.allApples.size //res2: Int = 1
ac.allOranges.size //res3: Int = 0

Importing generic implicits from class instances

I'm trying to make a generic implicit provider which can create an implicit value for a given type, something in the lines of:
trait Evidence[T]
class ImplicitProvider[T] {
class Implementation extends Evidence[T]
implicit val evidence: Evidence[T] = new Implementation
}
To use this implicit, I create a val provider = new ImplicitProvider[T] instance where necessary and import from it import provider._. This works fine as long as there is just one instance. However sometimes implicits for several types are needed in one place
case class A()
case class B()
class Test extends App {
val aProvider = new ImplicitProvider[A]
val bProvider = new ImplicitProvider[B]
import aProvider._
import bProvider._
val a = implicitly[Evidence[A]]
val b = implicitly[Evidence[B]]
}
And this fails to compile with could not find implicit value for parameter and not enough arguments for method implicitly errors.
If I use implicit vals from providers directly, everything starts to work again.
implicit val aEvidence = aProvider.evidence
implicit val bEvidence = bProvider.evidence
However I'm trying to avoid importing individual values, as there are actually several implicits inside each provider and the goal is to abstract them if possible.
Can this be achieved somehow or do I want too much from the compiler?
The issue is that when you import from both objects, you're bringing in two entities that have colliding names: evidence in aProvider and evidence in bProvider. The compiler cannot disambiguate those, both because of how its implemented, and because it'd be a bad idea for implicits, which can already be arcane, to be able to do things that cannot be done explicitly (disambiguating between clashing names).
What I don't understand is what the point of ImplicitProvider is. You can pull the Implementation class out to the top level and have an object somewhere that holds the implicit vals.
class Implementation[T] extends Evidence[T]
object Evidence {
implicit val aEvidence: Evidence[A] = new Implementation[A]
implicit val bEvidence: Evidence[B] = new Implementation[B]
}
// Usage:
import Evidence._
implicitly[Evidence[A]]
implicitly[Evidence[B]]
Now, there is no name clash.
If you need to have an actual ImplicitProvider, you can instead do this:
class ImplicitProvider[T] { ... }
object ImplicitProviders {
implicit val aProvider = new ImplicitProvider[A]
implicit val bProvider = new ImplicitProvider[B]
implicit def ImplicitProvider2Evidence[T: ImplicitProvider]: Evidence[T]
= implicitly[ImplicitProvider[T]].evidence
}
// Usage
import ImplicitProviders._
// ...

Method cannot be accessed in Macro generated class

I have the following macro defining a class and returning an instance of that class (with Scala 2.10.2 and the macro plugin):
def test[T] = macro testImpl[T]
def testImpl[T : c.WeakTypeTag](c: Context): c.Expr[Any] = {
import c.universe._
val className = newTypeName("Test")
c.Expr { q"""
class $className {
def method = 1
}
new $className
"""}
}
When I call the macro:
case class Cat(name: String)
val t = test[Cat].method
I get the following error:
method method in class Test cannot be accessed in Test
val t = test[Cat].method
^
My overall goal is to use vampire methods and to use quasi-quotes to describe the generated class. How can I solve this error?
In my post on vampire methods I mention this workaround for this bug. For some reason you currently aren't able to see an anonymous class's methods on the instance returned from the macro unless you create a wrapper class that extends the class with the methods and return an instance of that, instead.
You're seeing the same bug from a slightly different angle. You've named the class with the methods you want to see on the returned instance's structural type, but you still need a wrapper. The following will work:
c.Expr { q"""
class $className {
def method = 1
}
new $className {}
"""}
Note that all I've done is add a pair of brackets to the line creating the instance, so that I get an instance of an anonymous class extending $className instead of just a $className.
I have no idea what's behind this bug, and I'm not sure if Eugene knows more. I did recently confirm that it's still around in the latest build of 2.11.

Objects being "turned" to null randomly

Hey guys,
im working on a project in scala and i encountered very weird problem. This is a part of the code :
class Entity(val id:String){
override def toString = id
}
class RequirementType
case class DependsEither(t:List[(Entity,Int)]) extends RequirementType
case class Depends(t:(Entity,Int)) extends RequirementType
class BuildableEntity(override val id:String,
val mineralCost:Int,
val gasCost:Int,
val buildTime:Int,
val buildCount:Int,
val supplyCount:Int,
val req:List[RequirementType],
val onBuildStart: GameState => GameState,
val onBuildFinish: GameState => GameState
)extends Entity(id)
class SimpleBuilding(id:String,
mineralCost:Int,
gasCost:Int,
buildTime:Int,
req:List[RequirementType]
) extends BuildableEntity(id,mineralCost,gasCost,buildTime,1,0,req:::List(ConsumesOnStart((Drone,1))),{s=>s},{x=>x})
object SpawningPool extends SimpleBuilding("spawningPool",200,0,65,List(DependsEither(List((Hatchery,1),(Lair,1),(Hive,1)))))
object Lair extends SimpleBuilding("lair",150,100,80,List(ConsumesOnFinish(Hatchery,1),Depends(SpawningPool,1)))
object InfestationPit extends SimpleBuilding("infestationPit",100,100,50,List(DependsEither(List((Lair,1),(Hive,1)))))
Now, when i call println(Lair.req), it sometimes prints as
List(ConsumesOnFinish((hatchery,1)), Depends((null,2)), ConsumesOnStart((drone,1)))
and sometimes as
List(ConsumesOnFinish((hatchery,1)),
Depends((spawningPool,2)), ConsumesOnStart((drone,1)))
Please, if anyone has any idea about what could be going wrong, i would love you for ever. I have no clue why is it act as it does. I have more extensions of SimpleBuilding but they seem to be working properly
EDIT:
I should also mention that the outcome changes after compilation. I mean that when i run unit test it sometimes appear as null and sometimes as proper instance.
This is indeed a case of circular dependency and initialization. Here is a shorter version of your issue:
class X(val x: List[X])
object A extends X(List(B))
object B extends X(List(A))
object Main {
def main(args:Array[String]) {
println("A.x: " + A.x)
println("B.x: " + B.x)
}
}
This will print this:
$ scala -cp classes Main
A.x: List(B$#143c8b3)
B.x: List(null)
You can use by names parameter to allow object construction to finish before you use it:
class X(x0: => List[X]) {
lazy val x = x0
}
object A extends X(List(B))
object B extends X(List(A))
The fix works on the small test case:
$ scala -cp classes Main
A.x: List(B$#1feca64)
B.x: List(A$#6d084b)
Based on this you may want to change req:List[RequirementType] to req0: => List[RequirementType] and add a lazy val req = req0.
If that works for you, we should retitle the question to mention object initialization and circular dependencies. Note this is very similar to this question/answer.
Lair use SpawningPool in its constructor and reciprocally. But at that time, the other doesn't exists.
You've got recursive definitions in constructors, and although I believe that is supported, it looks like something's going wrong. Can you try lazy vals instead and see if the problem goes away? That is,
object X extends C("this",that,1) { /* code */ }
becomes
lazy val X = new C("this",that,1) { /* code */ }