Unable to create companion class instance in companion object method - scala

What's wrong with this code:
class Trivials(s:String){
private val x = 0
}
object Trivials {
def main(args: Array[String]): Unit = {
Trivials t = new Trivials("Trivials")
}
}
Both class and object are defined in same source file, hence they are companion.
Error message is as: 'Cannot resolve symbol t'

Wrong syntax (You are using Java syntax) for object creation. In case of Scala you need not mention the type in front of the variable t it will be automatically inferred.
Trivials t = new Trivials("Trivials")
Scala syntax
val t = new Trivials("Trivials")

Related

java.lang.ClassCastException when deserializing Scala object

So I have an object like this
case class QueryResult(events: List[Event])
that I need to serialize deserialize. For serialization I have this implicit class
implicit class Serializer(obj: Object) {
def serialize: Array[Byte] = {
val stream = new ByteArrayOutputStream()
val objectOutputStream = new ObjectOutputStream(stream)
objectOutputStream.writeObject(obj)
objectOutputStream.close
stream.toByteArray
}
}
It's used like
val byteArray = QueryResult(events).serialize
Then for desrialization I have this trait that can be extended by the companion class.
trait Deserializer[A] {
private type resultType = A
def deserialize(bytes: Array[Byte]): A = {
val objectInputStream = new ObjectInputStream(
new ByteArrayInputStream(bytes)
)
val value = objectInputStream.readObject.asInstanceOf[resultType]
objectInputStream.close
value
}
}
You would use it like so
object QueryResult extends Deserializer[QueryResult]
Then you should be able to reconstruct an instance of QueryResult from a byte array like so
val QueryResult: QueryResult = QueryResult.deserialize(byteArray)
The issue is this sometimes causes an error like the one below
java.lang.ClassCastException: cannot assign instance of scala.collection.generic.DefaultSerializationProxy to field co.app.QueryResult.events of type scala.collection.immutable.List in instance of co.app.QueryResult
at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2205)
at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2168)
at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1422)
at java.base/java.io.ObjectInputStream.defaultCheckFieldValues(ObjectInputStream.java:2450)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2166)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1668)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:482)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:440)
at co.app.Deserializer.deserialize(Types.scala:51)
at co.app.Deserializer.deserialize$(Types.scala:47)
at co.app.LocalStorage$QueryResults$.get(LocalStorage.scala:241)
... 36 elided
Now when I say sometimes I mean the deserialization works when I assemble the code into a jar and run it using the java cli, but it breaks when I try to execute that code via sbt test, sbt console, or ammonite. Any idea why it breaks under these circumstances and possible suggestions to fix?

Scala standalone object not getting recognized

I am creating a singleton object using script xyz.scala as follow :
object ChecksumCalculator {
def calcChecksum(s: String): Int = {
val cc = new ChecksumCalculator
for (c <- s)
cc.add(c.toByte)
cc.checksum
} }
When I run this as script as Scala xyz.scala ,
I am getting the error as :
01HW993798:scala tcssig$ scalac xyz.scala
xyz.scala:3: error: not found: type ChecksumCalculator
val cc = new ChecksumCalculator
^
one error found
Although I have declared the standalone object at the top, is it possible that my standalone object is not getting recognized.
Or is it due to some other error ?
In scala, singleton objects are instantiated on usage and guaranteed to be instantiated only once, hence providing strict "singleton" semantics.
Assuming that your object has method "add(b:Byte)" you could do:
CheckSumCalculator.add(c.toByte)
But given that we are in the scope of CheckSumCalculator, using this should be sufficient:
add(c.toByte)
That said, using a singleton object for mutable operations seems a bad idea.
It looks like that what you are looking for is to create instances of some class, but also have some facility method that can be called statically.
That construction has a name in Scala: A companion object
companion objects are defined by creating an object of the same name as some given class.
Translating that to this scenario, we would have:
class ChecksumCalculator {
def add(b:Byte) = ???
def checksum(): Int = ??? // or whatever type the checksum is
}
object ChecksumCalculator { // this is a companion object
def calcChecksum(s: String): Int = {
val cc = new ChecksumCalculator
s.foreach(c => cc.add(c.toByte))
cc.checksum()
}
}

Scala: "In-place" the trait Inheriting without "new" keyword

I can't understand why a syntax error occurs in this code:
"T.scala" file:
trait T
"A.scala" file:
class A
object A {
def apply() = new A()
}
"other.scala" file:
val a = new A() with T // ok
val b = A() with T // syntax error ';' or newline expected
Can I create a new class instance with inheriting without using the new keyword?
I've not found anything about it.
A() translates to A.apply() which is a method that returns a new object and is not the same as new A().
You are essentially trying to do this (which will not work):
val b = A.apply()
val c = b with T
You can't use with on an object that has already been created.

Create companion objects for classes imported from Java

I want to create companion objects for some imported Java types, so that I do not have to use new to allocate them. I want to start with the type Vector3f is imported from com.jme3.math from jMonkeyEngine.
What I tried is:
package com.jme3.math
object Vector3f {
def apply() = new Vector3f()
def apply(x:Float, y:Float, z:Float) = new Vector3f(x,y,z)
}
When compiling this, I get errors:
Error:(8, 21) not found: type Vector3f
def apply() = new Vector3f()
When I add import com.jme3.math.Vector3f, I get warning which probably explains what I see:
Warning:(3, 22) imported `Vector3f' is permanently hidden by definition of object Vector3f in package math
How can I create a companion object for com.jme3.math.Vector3f or other types imported from Java?
That's a naming issue, you can't have both the Java class and Scala companion object with the same name there.
Either you access Java class inside companion object with the fully qualified name new com.jme3.math.Vector3f(...) or you indicate a different local name while importing it.
import com.jme3.math.{ Vector3f => JV3 }
def apply(): JV3 = new JV3()
Extra example (companion object for Java class org.apache.http.HttpClient):
import org.apache.http.client.{ HttpClient ⇒ HC }
object HttpClient {
def apply(): HC = ???
}
Or...
// No import
object HttpClient {
def apply(): org.apache.http.client.HttpClient = ???
}

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.