scala inherited value do not find - scala

Scala version 2.11.8
I have parent class
abstract class FR(externalId:String, code:String, message:String) extends Serializable {
val this.externalId=externalId;
val this.code = code;
val this.message = message;
def toString:String={
return "FRworks";
}
}
The child class is:
class RD extends FR {
def this(lpTransaction:LPTransaction)={
externalId =lpTransaction.getField("somethinghere").toString
...
}
}
The error is:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading project definition from F:\workspace\frankcheckAPI\project
[info] Set current project to frankcheckapi (in build file:/F:/workspace/frankcheckAPI/)
[info] Compiling 20 Scala sources to F:\workspace\frankcheckAPI\target\scala-2.11\classes...
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\fraudcheck\RD.scala:9: 'this' expected but identifier found.
[error] externalId =lpTransaction.getField("somethinghere").toString
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
when I add this in front of externalId the error still:
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
[info] Loading project definition from F:\workspace\frankcheckAPI\project
[info] Set current project to frankcheckapi (in build file:/F:/workspace/frankcheckAPI/)
[info] Compiling 20 Scala sources to F:\workspace\frankcheckAPI\target\scala-2.11\classes...
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\fraudcheck\ReDFraudCheckResponse.scala:9: '}' expected but '.' found.
[error] this.externalId =lpTransaction.getField("somethinghere").toString
[error] ^
[error] F:\workspace\frankcheckAPI\src\main\scala\com\cardaccess\fraudcheck\ReDFraudCheckResponse.scala:12: eof expected but '}' found.
[error] }
[error] ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed

Your code is very Java-influenced. There are couple of things wrong here; when you fix the obvious ones like missing class parameters in RD it boils down to not being able to reassign to val.
Let me give you an improved, Scala-fied version of the whole code.
abstract class FR(val externalId: String, val code: String, val message: String) extends Serializable
// dummy class
class LPTransaction {
def getField(s: String) = s
}
class RD(externalId: String, code: String, message: String) extends FR(externalId, code, message) {
def this(lpTransaction: LPTransaction) = {
this(lpTransaction.getField("somethinghere").toString, "defaultCode", "defaultMessage")
}
println(externalId)
}
val a = new RD(new LPTransaction) // prints "somethinghere"
Main improvements are:
You don't need private fields to be populated using arguments in the constructor. Scala favors immutability. Make your class arguments "vals", this means they will be available as public fields (instead of getters you will access them directly; this is contrary to OOP's encapsulation principle, but here it's ok because nobody can mess with them anyway since they are immutable; they may only be fetched)
Your subclass RD should be taking same fields as parameters as its parent class. Of course, you can then define an auxiliary constructor that takes only LPTransaction, but then you need to feed the parent class with some default values for the other parameters.
The rest kind of follows from this. I added the dummy implementation of LPTransaction to be able to compile. I also threw in a println statement in RD class just for the sake of example. Feel free to ask if something's not clear.

//scala automatically generates getters for passed in params. No need to set them explicitly. For immutable params use val, for mutable use var
abstract class FR(var externalId:String, val code:String, val message:String) extends Serializable {
//need to use override annotation for superclass methods
override def toString:String={
return "FRworks";
}
}
// notice how constructor parameters are passed to the base class when defining the child class.
class RD extends FR("someID","code","msg") {
def printId() = println(externalId)
}
val x = new RD
x.externalId = "new ID" //works because externalId is var (mutable)
x.code = "new code" //error because code is val (immutable)
x.printId //correctly prints the external id: someID

Related

Why is the Scala compiler giving me an error when passing a Kotlin sealed class into a constructor?

I have a sealed class, written in Kotlin:
sealed class Schema {
class RecordSchema(val fields: List<Field>): Schema()
class ArraySchema(val elementSchema: Schema): Schema()
...
}
And another class that takes RecordSchema as a parameter:
class Enrichment(config: Config, val schema: RecordSchema) { ... }
In Scala I have a class that, among other things, get an instance of the RecordSchema and then create an instance of the Enrichment.
object Job {
def main(args: Array[String]): Unit = {
/// some initializing of resources... and then...
val recordSchema = schemas.getSchema(id) // type is Schema.RecordSchema
val enrichment = Enrichment(config, recordSchema) // this is where scalac errors out
}
}
The scala compiler ends up printing this error message:
Error:(52, 62) type mismatch;
found : com.companyname.enricher.schemas.com.companyname.enricher.schemas.com.companyname.enricher.schemas.
required: com.companyname.enricher.schemas.(some other)com.companyname.enricher.schemas.com.companyname.enricher.schemas.
val enrichment = new Enrichment(config, recordSchema)
If I cast recordSchema using asInstanceOf I get another, not so useful, error:
Error:(52, 62) type mismatch;
found : com.companyname.enricher.schemas.Schema.RecordSchema
required: com.companyname.enricher.schemas.com.companyname.enricher.schemas.
val enrichment = new Enrichment(config, recordSchema.asInstanceOf[RecordSchema])
Overall, I have no idea why this is happening. If I make the constructor take the parent class as a parameter rather than nested class, it compiles just fine (which is my workaround for now). If I do the same type of thing, except having written the sourcecode in Java rather than Kotlin, this error does not happen. I am using Java 1.8, Kotlin 1.0.4, Scala 2.11.8.
UPDATE:
demonstrated bug here:
https://github.com/mjburghoffer/scala-kotlin-innerclass-bug/tree/master
Looks like Kotlin generates different number of classes for this case. I compiled Java and Kotlin sources and found that Java has additional file ParentSealedJava$1.class. Bytecode of Parent and Sealed classes in Java and Kotlin pretty the same (i inspect bytecode using javap -c), so i think Scala compiler relies somehow on this missing file in Kotlin.

Scala value has incompatible type?

I am still new enough to Scala that the typing system is destroying me. I haven't yet thought of a solution or discovered a pattern that gets around this particular problem that I am trying to solve. Consider the following program:
ShapeType.scala
package models
abstract class ShapeType {
val themes: ShapeThemes[ShapeTheme] // I think this is where the problem is...?
}
class CircleShapeType extends ShapeType {
val themes = CircleShapeThemes
}
object CircleShapeType extends CircleShapeType
ShapeThemes.scala
package models
abstract class ShapeThemes[T <: ShapeTheme] {
val themes: List[T]
}
class CircleShapeThemes extends ShapeThemes[CircleShapeTheme] {
val themes = List(
new CircleShapeTheme,
new CircleShapeTheme,
new CircleShapeTheme
)
}
object CircleShapeThemes extends CircleShapeThemes
ShapeTheme.scala
package models
class ShapeTheme
class CircleShapeTheme extends ShapeTheme
When I attempt to compile the program (using sbt), I get the following error:
[error] /Users/mjs/Projects/sandbox/shape-types/src/main/scala/ShapeType.scala:8: overriding value themes in class ShapeType of type models.ShapeThemes[models.ShapeTheme];
[error] value themes has incompatible type
[error] val themes = CircleShapeThemes
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 2 s, completed Mar 14, 2015 5:08:43 PM
However, as far as I can tell, CircleShapeThemes is a ShapeThemes[ShapeTheme]. What am I missing?
CircleShapeThemes is not a ShapeThemes[ShapeTheme], it's a ShapeThemes[CircleShapeTheme].
"But", you may object, "a CircleShapeTheme is a ShapeTheme! Indeed, but that subclass relationship isn't propagated by default. You have to ask for it by making the type parameter covariant: abstract class ShapeThemes[+T <: ShapeTheme]

How do I leveraging SLF4J varargs logging in Play2.1 framework?

SLF4J's varargs on the logging calls are quite useful in my Java work
Logger log = LoggerFactory.getLogger( getClass() );
log.debug( "Hello, {}. The current time is {}", "robert", new Date() );
Attempting to do this simple example in Play 2.1 Framework/Scala and I run into the compiler rejecting me.
import play.api._
import play.api.mvc._
import org.slf4j.LoggerFactory
object Application extends Controller {
val log: org.slf4j.Logger = LoggerFactory.getLogger(getClass())
def hb = Action {
val message = makeMessage()
// COMPILER HATES THIS: ambiguous reference compiler error here
log.info("Hello {}. The current time is {}", "robert", new java.util.Date() )
Ok(message)
}
def makeMessage(): String = { return "stuff" }
}
[dm2-server] $ compile
[info] Compiling 2 Scala sources to /Users/bobk/work/dm2-server/target/scala-2.10/classes...
[error] /Users/bobk/work/dm2-server/app/controllers/Application.scala:16: ambiguous reference to overloaded definition,
[error] both method info in trait Logger of type (x$1: String, x$2: <repeated...>[Object])Unit
[error] and method info in trait Logger of type (x$1: String, x$2: Any, x$3: Any)Unit
[error] match argument types (String,String,java.util.Date)
[error] log.info("Hello {}. The current time is {}", "robert", new java.util.Date() )
[error] ^
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 1 s, completed Jun 6, 2013 10:54:41 AM
What is that error and how do I overcome it to call through to the SLF4J API? If I can't do that, how can I use the Play 2.1 Logging Framework to get varargs on my logging calls? Something is not right in Scala-land.
What version of SLF4J are you using? If you can go back to 1.6.6 or later, you can avoid this issue in ambiguity. Those two signatures unfortunately look the exact same to scala and the compiler can't seem to differentiate which one you mean. The common suggestion is to roll back to a version of SLF4J (if even possible for you) where this overloaded method ambiguity will not exist. More info can be found at the links below:
https://groups.google.com/forum/?fromgroups#!topic/scala-language/ms4IVIu-xGw
https://github.com/typesafehub/scalalogging/issues/16
The "quick fix" for this is as follows:
Just force the last argument to be type Any and that resolves the compiler's issue(s) (and makes for slightly less code...)
logger.debug("hello {} / {} ", "Hello", "World":Any)
Or in your case:
log.info("Hello {}. The current time is {}", "robert", new java.util.Date():Any)

How to I override a Java varargs method in Scala?

I have a method defined in Java like:
void foo(int x, Thing... things)
I need to override that in Scala, but both of these give errors:
override def foo(x: Int, things: Thing*)
override def foo(x: Int, things: Array[Thing])
The errors refer to <repeated...> but I don't know what that is.
Update
Ugg... nevermind. I'm in 2.10.0, and I had mis-typed something and didn't have a method body. Then I got confused by this error message, which still seems a odd to me. In SBT:
> compile
[info] Compiling 1 Scala source to [...]/target/scala-2.10/classes...
[error] [...]/src/main/scala/Translator.scala:41: class MyMethodVisitor needs to be abstract, since method visitTableSwitchInsn is not defined
[error] (Note that org.objectweb.asm.Label* does not match <repeated...>[org.objectweb.asm.Label])
[error] class MyMethodVisitor extends MethodVisitor (Opcodes.ASM4) {
[error] ^
The problem is that my visitTableSwitchInsn simply lacks a body, but the error suggests that the problem is the type of the varargs parameter.
Java:
package rrs.scribble;
public
class VA1
{
public int va1(int... ints) {
return ints.length;
}
}
Scala:
package rrs.scribble
class VA1S
extends VA1
{
override
def va1(ints: Int*): Int =
ints.length * 2
}
SBT:
> ~compile
[info] Compiling 1 Scala source and 1 Java source to …/scribble/target/scala-2.10/classes...
[success] Total time: 4 s, completed Jan 15, 2013 3:48:14 PM
1. Waiting for source changes... (press enter to interrupt)
This is Scala 2.10, which is consistent with #TravisBrown's comment.

How to implement a partial function in a subclass

I'm trying to design a couple of classes that inherit a partial function, but I don't seem to be able to get the syntax quite right. My superclass looks like this:
abstract class Controller {
val react:PartialFunction[Event,Unit]
}
And the subclass looks like:
class BoardRendererController(val renderer:BoardRenderer, val board:Board) extends Controller {
override val react {
case PieceMovedEvent(piece, origin, destination) => println("Moving now")
}
}
But this fails to compile with this error
[ERROR] /workspace/pacman/src/main/scala/net/ceilingfish/pacman/BoardRendererController.scala:14: error: '=' expected but '{' found.
[INFO] override val react {
[INFO] ^
[ERROR] /workspace/pacman/src/main/scala/net/ceilingfish/pacman/BoardRendererController.scala:17: error: illegal start of simple expression
[INFO] }
[INFO] ^
I've tried loads of variations on this, anyone know what the correct syntax is?
In addition to abhin4v's terse suggestion, you still have to supply a type annotation in the definition, so I recommend this addition to your base class:
type PFEU = PartialFunction[Event, Unit]
Then your subclass would look like this:
class BoardRendererController(val renderer:BoardRenderer, val board:Board)
extends Controller
{
override val react: PFEU = {
case PieceMovedEvent(piece, origin, destination) => println("Moving now")
}
}