Getting Scala enum instances - scala

I have the following Scala enum which I designed after reading this answer:
object RunMode extends Enumeration {
val CLIENT_MODE = Value("CLIENT_MODE")
val SERVER_MODE = Value("SERVER_MODE")
}
I am now trying to pass an instance of it as an argument into the constructor of another class:
package com.me.myapp.shared.config
import com.me.myapp.shared.utils.RunMode
class MyAppConfig(runMode : RunMode) {
}
This gives me a compiler error:
Cannot resolve symbol RunMode
BTW: com.me.myapp.shared.utils.RunMode is the correct package path for RunMode, so that's not the issue here!
I assume that this is maybe because there is only (ever) one single instance of the RunMode object, and perhaps that prevents it from being passed in as an arg.
Either way, I don't really care what the solution is. But I need an "enum" called RunMode and I'll need to be able to pass instances of it into contructors of other classes. Any ideas?

You are almost there, the correct type for a value of an Enumeration is Enumeration.Value, so here you need to use:
class MyAppConfig(runMode : RunMode.Value) {
}

You're correct in the assumption that the only instance that inhabits the type RunMode is the object itself.
However fixing your problem isn't all that difficult.
object RunMode extends Enumeration {
type RunMode = Value
val CLIENT_MODE = Value("CLIENT_MODE")
val SERVER_MODE = Value("SERVER_MODE")
}
The Enumeration class gives you the type Value which is the type that all of your enumerated types should have. It's scoped to the class instance, so every instance of Enumeration get's its own Value type.
You can give it a proper name by creating a type alias.
Then you can import the inner type alias like this:
import com.me.myapp.shared.utils.RunMode._
And then you can pass Instances of your Enumeration around, therefore also allowing you to keep the MyAppConfig the same as it is right now.
Alternatively, you could of course also omit the type alias and just change the type signature of MyAppConfig to RunMode.Value. However I believe the former method is much better at clarifying intent.
class MyAppConfig(runMode: RunMode.Value) {
}

Related

Scala, why do I not need to import deduced types

I feel like I should preface this with the fact that I'm building my projects with sbt.
My problem is that, if at compile time a method returns something of an unimported type, in the file where I call the method, as long as I use type inference, everything compiles. Once I try to assign the unimported type to the var/val which I created with the return value of my function, I get a compiler error.
Lets say I have two classes in two package. Class App in package main and class Imported in package libraries. Lets further more say that we have a class ImportedFactory in the package main and that this class has a method for creating objects of the type Imported.
This code compiles just fine:
class App() {
// method return object of type Imported
val imp = ImportedFactory.createImportedObject()
}
This doesn't:
class App() {
// method return object of type Imported
val imp : Imported = ImportedFactory.createImportedObject()
}
This yet again does:
import libraries.Imported
class App() {
// method return object of type Imported
val imp : Imported = ImportedFactory.createImportedObject()
}
This seems like rather strange behavior. Is this normal for languages with type inference at compile time and I've yet to notice it until now in go/C++ due to my ignorance ?
Does one of the two valid approaches (import&explicit type vs infered) have advantages/drawback over the other ? (expect for, of course, one being more explicit and verbose and the other one being shorter)
Is this black magic or does the Scala compiler accomplish these deductions in a rather straight forward way ?
The only thing importing does is making a not fully qualified name available in the current scope. You could just as well write this:
class App() {
val imp: libraries.Imported = ImportedFactory.createImportedObject()
}
The reason you import libraries.Imported is for making the shorter name Imported available for you to write. If you let the compiler infer the type, you don't mention the type in your code, so you don't have to import its shorter name.
And by the way: this has nothing to do with dynamic casting in C++. The only mechanism at work in your code is type inference.
note: You'll get better search results with the term type inference
With val imp = ImportedFactory.createImportedObject() you are letting the compiler figure out what type imp should be based on type inference. Whatever type createImportObject returns, that's what type imp is.
With val imp : Imported = ImportedFactory.createImportedObject() you are explicitly stating that imp is an Imported. But the compiler doesn't know what you mean by that unless you... import... it.
Both approaches have merit:
inferred types
Inferred types are great for when you're throwing together code where the type should be obvious:
val i = 1 // obviously `i` is an int
val j = i + 10 // obviously still an int
It's also great for local vars/vals where the type would be too much of a pain to write
val myFoo: FancyAbstractThing[TypeParam, AnotherTypeParam[OhNoMoreTypeParams]] = ...
// vs
val myFoo = FancyThingFactory.makeANewOne()
The downside is that if you have allowed a public def/val to have an inferred type, it can be more difficult to determine how to use that method. For this reason, omitting type annotations is typically only used for simple constants, and in local vals/vars that "client code" doesn't have to look at.
explicit types
When you do want to write library-ish code (i.e. public vals/defs), the convention is to explicitly-type them.
Probably the simplest reason for this is because this:
def myLibraryMethod = {
// super complicated implementation
}
is harder to understand than
def myLibraryMethod: String = {
// super complicated implementation
}
Another benefit to explicitly-typing your code is when you want to expose a less-specific type than what the value actually is:
val invalidNumbers: Set[Int] = TreeSet(4, 8, 15, 16, 23, 42)
In this example, you don't want client code to need to care that your invalidNumbers is actually a TreeSet. That's an implementation detail. In this case you're hiding some information that, while true, would be distracting.

How to get a Scala runtime class with generic parameters?

I wonder if it is possible to do something like the following:
import scala.reflect.runtime.universe._
class Bar[T]
def foo[T]()(implicit ctag: reflect.ClassTag[T]) {
val clazz = classOf[Bar[ctag.runtimeClass.asInstanceOf[Class[T]]]]
}
Here the Scala compiler complains:
error: stable identifier required, but ctag.runtimeClass found.
Is there a way to get the class type with type parameters inserted from the runtime type information available in the function?
Is there a way to get the class type with type parameters inserted from the runtime type information available in the function?
classOf[Bar[T]] works for a very simple reason: it doesn't insert any runtime information! classOf[Bar[T]], classOf[Bar[String]], classOf[Bar[Int]], classOf[Bar[_]] are all the same; that's what type erasure means in JVM context (to avoid misleading, I prefer always using classOf[Bar[_]] where possible). Note that there is actually a single exception: if Bar is Array, because classOf[Array[Int]] and classOf[Array[Object]] (e.g.) are different!
classOf[T] obviously would need runtime information and so it doesn't work.
Thanks to the comment by #Mr. V I realized that its actually easier than I initially thought:
import scala.reflect.runtime.universe._
class Bar[T]
def foo[T]() {
val clazz = classOf[Bar[T]]
}

Scala class that handles enumerations generically

I want to create a generic class that holds the value of an enumeration, and also allows access to the possible values of the enumeration. Think of a property editor for example - you need to know the current value of the property, and you also need to be able to know what other values are legal for the property. And the type of enumeration should not be known in advance, you should be able to work with any kind of enumeration.
My first thought was something like this:
class EnumerationProperty[T <: Enumeration](value:T)
However, that doesn't work because for enumerations T isn't a type, it's an object. Other variations I have tried are:
class EnumerationProperty[T <: Enumeration](value:T.Value)
class EnumerationProperty[T <: Enumeration.Value](value:T)
(I won't go into the details of why these don't work because I suspect the reasons aren't interesting.)
For first part of your question. You can define holder for generic enum value like this:
case class EnumerationProperty[T <: Enumeration#Value](value:T)
But I don't know how to get all enum values without explicitly pass Enumeration object. Enumeration has values() method to get all values. And Enumeration#Value has link to Enumeration, but with private access
In your use case (a property editor) I think the best solution is to rely on scala reflection available in scala 2.10. Given a class's TypeTag, you can get the full type (without erasure) of all of its members plus their values, and from that populate your property editor. For enumerations, use the TypeTag to get their values using the following method:
Using Scala 2.10 reflection how can I list the values of Enumeration?
Now, maybe you don't want or can't use scala reflection, and from now on I'll suppose this is the case. If that is true then you are opening a whole can of worm :)
TL;DR: This is not possible using a standard Enumeration, so you'll probably have to explcitly wrap the enumeration values as shown in Ptharien's Flame's answer (or roll your own fork of Enumeration). Below I detail all my attempts, please bear with me.
Unfortunately, and for some unknown reason to me (though I suspect it has to do with serialization issues), Enumeration.Value has no field pointing to its Enumeration instance. Given how Enumeration is implemented, this would be trivial to implement, but of course wehave no say, short of forking Enumeration and modifying our version (which is actually what I did for this very purpose, plus to add proper support for serialization and reflection - but I diggress).
If we can't modify Enumeration, maybe we can just extend it? Looking at the implementation again, something like this would seem to work:
class EnumerationEx extends Enumeration {
protected class ValEx(i: Int, name: String) extends Val(i, name) {
#transient val enum: Enumeration = EnumerationEx.this
}
override protected def Value(i: Int, name: String): Value = new ValEx(i, name)
}
object Colors extends EnumerationEx {
val Red, Green, Blue = Value
}
The downside would be that it only works for enumerations that explicitly extend EnumerationEx instead of Enumeration, but it would be better than nothing.
Unfortunately, this does not compile simply because def Value ... is declared final in Enumeration so there is no way to override it. (Note again that forking Enumeration would allow to circunvent this. Actually, why not do it, as we are already down the path of using a custom Enumeration anwyay. I'll let you judge).
So here is another take on it:
class EnumerationEx extends Enumeration {
class ValueWithEnum( inner: Value ) {
#transient val enum: Enumeration = EnumerationEx.this
}
implicit def valueToValue( value: Value ): ValueWithEnum = new ValueWithEnum( value )
}
And indeed it works as expected. Or so it seems.
scala> object Colors extends EnumerationEx {
| val Red, Green, Blue = Value
| }
defined module Colors
scala> val red = Colors.Red
red: Colors.Value = Red
scala> red.enum.values
res58: Enumeration#ValueSet = Colors.ValueSet(Red, Green, Blue)
Hooray? Well no, because the conversion from Value to ValueWithEnum is done only when accessing red.enum, not at the time of instantiation of the Colors enumeration. In other words, when calling enum the compiler needs to know the exact static type of the enumeration (the compiler must statically know that red's type is Colors.Value, and not just Enumeration# Value). And in the use case you mention (a property editor) you can only rely to java reflection (I already assumed that you won't use scala reflection) to get the type of an enumeration value, and java reflection will only give you Enumeration#Val (which extends Enumeration#Value) as the type of Colors.Red. So basically you are stuck here.
Your best bet is definitly to use scala reflection in the first place.
class EnumProps[E <: Enumeration](val e: E)(init: e.Value) {...}
Then you can use e and e.Value to implement the class.

Scala inheritance with a abstract class

I am new to scala, just doing some practice;
I tried a very simple program, briefed as following:
abstract class Device(val cds: Array[Char]) {
var codes = Array[Char](cds: _*)
def encrpt(code: Char): Char
var nextDevice: Device
def setNext(next: Device):Unit = {
nextDevice = next
}
}
//compiler error shows here
class Input(codes: Array[Char]) extends Device(codes) {
override def encrpt(code: Char) = code
}
you could see there is a compiler error at line 21, following is the message:
class Input needs to be abstract, since variable nextDevice in class Device of type com.me.acm.problem1009.Device is not
defined (Note that variables need to be initialized to be defined)
I am pretty confusing that error, my understanding, define some variable and an setter method in the parent class, so the child classes can use it without define it again. it is straight forward.
I guess I missed something. Could someone explain it to me and tell what is the correct way? thanks.
In Scala, variables do not have assumed default values as they do in Java (or many other languages). Thus, when you declare a variable, you must always specify its initial value.
In your code, you declare a variable nextDevice, but you do not give it a value. Since Scala always needs a value, it interprets what you've written as nextDevice being an abstract field, so the compiler is telling you that it must be overridden.
If you change that line to the following, for example, to specify an initial value, then the error will disappear:
var nextDevice: Device = new Input(Array())
As the error message is telling you, the variable nextDevice needs to be initialized in the constructor on Input.
class Input(codes: Array[Char]) extends Device(codes) {
override def encrpt(code: Char) = code
nextDevice = null
}
Note that using null is frowned upon in Scala. You should probably change the type of your variable to Option[Device]

Scala class constructor local parameters

Can I pass arguments to Scala class constructor that are not stored into class itself?
I want to achieve functionality which in Java could be written as follows:
class A {
private final SomethingElse y;
public A(Something x) {
y = x.derive(this);
}
}
I.e. class constructor takes parameter that is later transformed to another value using reference to this. The parameter is forgotten after constructor returns.
In Scala I can do:
class A(x: Something) {
val y = x.derive(this)
}
But it means that x is stored in the class, which I want to avoid. Since x.derive method uses reference to this, I can not make the transformation in companion object.
But it means that x is stored in the class, which I want to avoid.
If you don't reference constructor argument anywhere except the constructor itself, field won't be created. If you reference x e.g. in toString(), Scala will automatically create and assign private val for you.
Use javap -c -private A to verify what kind of fields are actually created.
BTW you pass this inside a constructor, which means a.derive() gets a reference to possibly non-initialized instance of A. Be careful!