How to assign enum type arguement in scala - scala

object StorageType extends Enumeration{
type Name = Value
val HTML, TEXT, SUBJECT = Value
}
def read(key:String, _type:StorageType.Value = StorageType.HTML):String = {
val accessKey = getPrefix(_type) + key
DaoFactory.getPreviewStorageDao.get(accessKey).data
}
Does this mean I can only send StorageType.HTML as argument and not StorageType.SUBJECT?
Also I am pretty new to scala so can you tell me what exactly does _type do here?

The _type parameter can be any one of the StorageType.Value instances, but if you don't put any instance into it when you call the method, then the StorageType.HTML instance will be automatically assigned.

Related

In scala 2.13.x, is there a way to loop over the values of a Enumeration where Value is a String?

I have an enumeration like this:
object UserType extends Enumeration {
type UserType = String
val member = "member"
val admin = "admin"
}
Is there a way to get all the values of the Enumeration so it returns:
val userTypes: Set[String] = UserType.values.toSet
For some reason UserType.values returns of type UserType.Value or something, not a string.
Is there a way to accomplish this?
If you want use Enumeration need set Value to your type:
type UserType = Value
And then define variable as:
val admin = Value("admin")
Otherwise, you don't use a Enumeration.
For get list of all values:
UserType.values.toList

How to reflect Enumeration class in scala?

I have a Scala Enumeration and I want to get the Enumeration value from String.
object CVVStatus extends Enumeration {
type CVVStatus = Value
val PRESENT, NOT_PRESENT, VALID, INVALID = Value
}
I want to do something like this:
val prop = new Properties()
prop.load(new FileInputStream("config.conf"))
val tmp = prop.getProperty(propname)
val s:CVVStatus = StringtoEmum(tmp)
If I need lots of enumeration from different Enumeration object-name to enumeration objects, how should I accomplish this? What package should I import?
As #Alec points out in a comment, this is 'for free' with the Enumeration class, and it is easy to see in a worksheet:
object CVVStatus extends Enumeration {
type CVVStatus = Value
val PRESENT, NOT_PRESENT, VALID, INVALID = Value
}
val test_present = "PRESENT" // test_present: String = PRESENT
val test_incorrect = "INCORRECT" // test_incorrect: String = INCORRECT
val enumeration_present = CVVStatus.withName(test_present) // enumeration_present: CVVStatus.Value = PRESENT
val enumeration_incorrect = CVVStatus.withName(test_incorrect) //java.util.NoSuchElementException: No value found for 'INCORRECT'
This last one fails, because it is not a valid enumeration. The withName documentation reads:
Return a Value from this Enumeration whose name matches the argument s. The names are determined automatically via reflection.
No imports necessary.
You may also consider using case objects. For reference, check these stackoverflow answers
Case Objects vs Enumerations
How to access objects within an object by mixing in a trait with reflection?

Scala Default Values: How do I get a default value from type Any in Scala while creating a LinkedList?

I am creating a Doublelylinked list in Scala and I have having a problem creating the sentinel node. For my sentinel node's data, I need the default value of the type I am using (EX: I need 0 for Int or null for String). Just using A does not get this value, Scala Manifest does not give me the value. Any ideas on how to get the default value for Any in Scala at this situation in Eclipse?
class DoubleLinkList[A : Manifest] extends List[A] {
private class Node (var data: A, var previous:Node, var next:Node)
private var end:Node new Node(A, null, null) //I need the default value of the type I am using for A in this situation.
end.prev = end
end.next = end
}
That works (in console at least, scala 2.10.3):
scala> def defval[A:Manifest]() = null.asInstanceOf[A]
defval: [A]()(implicit evidence$1: Manifest[A])A
scala> defval[Boolean]
res26: Boolean = false

Scala Getting class type from string representation

I have a class name string representation
val cls = Class.forName("clsName")
def fromJson[T: Manifest](me: String): T = {
Extraction.extract[T](net.liftweb.json.parse(me))
}
I would like to use it as T:manifest i.e
JsonConverter.fromJson[cls.type](stringData)
this returns an error
tried also
val t = Manifest.classType(cls)
JsonConverter.fromJson[t](stringData) // compile error
what is the best way to it ? is there a way to avoid using reflection ?
You could try something like this:
val cls = Class.forName(myClassName)
val m = Manifest.classType(cls)
val myObj:Any = JsonConverter.fromJson(stringData)(m)
One nuance to this approach is that you have to explicitly type the object as an Any. This is because you don't have the class as compile time and the call to classType is not supplied its type param so the Manifest returned is Manifest[Nothing]. Not ideal, but it works.

Scala class members and constructor parameters name clash

Consider the following class written in Java:
class NonNegativeDouble {
private final double value;
public NonNegativeDouble(double value) {
this.value = Math.abs(value);
}
public double getValue() { return value; }
}
It defines a final field called value that is initialized in the constructor, by taking its parameter called alike and applying a function to it.
I want to write something similar to it in Scala. At first, I tried:
class NonNegativeDouble(value: Double) {
def value = Math.abs(value)
}
But the compiler complains: error: overloaded method value needs result type
Obviously the compiler thinks that the expression value inside the expression Math.abs(value) refers to the method being defined. Therefore, the method being defined is recursive, so I need to state its return type. So, the code I wrote does not do what I expected it to do: I wanted value inside Math.abs(value) to refer to the constructor parameter value, and not to the method being defined. It is as if the compiler implicitly added a this. to Math.abs(this.value).
Adding val or var (or private ... variants) to the constructor parameter doesn't seem to help.
So, my question is: can I define a property with the same name as a constructor parameter, but maybe a different value? If so, how? If not, why?
Thanks!
No, you can't. In Scala, constructor parameters are properties, so it makes no sense to redefine them.
The solution, naturally, is to use another name:
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
Used like this, initValue won't be part of the instances created. However, if you use it in a def or a pattern matching declaration, then it becomes a part of every instance of the class.
#Daniel C. Sobral
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
your code is right, but "constructor parameters are properties",this is not true.
A post from the official site said,
A parameter such as class Foo(x : Int) is turned into a field if it is
referenced in one or more methods
And Martin's reply confirms its truth:
That's all true, but it should be treated as an implementation
technique. That's why the spec is silent about it.
So normally, we can still treat primary constructor parameters as normal method parameter, but when the parameters is referenced by any of the methods, the compiler will cleverly turn it into a private field.
If any formal parameter preceded by the val, the compiler generates an getter definition automatically.if var, generates a setter additionally. see the language speification section 5.3.
That's all about primary constructor parameters.
You can consider parametric field
class NonNegativeDouble(val value: Double, private val name: String ){
if (value < 0) throw new IllegalArgumentException("value cannot be negative")
override def toString =
"NonNegativeDouble(value = %s, name = %s)" format (value, name)
}
val tom = "Tom"
val k = -2.3
val a = new NonNegativeDouble(k.abs, tom)
a: NonNegativeDouble = NonNegativeDouble(value = 2.3, name = Tom)
a.value
res13: Double = 2.3
a.name
<console>:12: error: value name in class NonNegativeDouble cannot be accessed in NonNegativeDouble
a.name
val b = new NonNegativeDouble(k, tom)
java.lang.IllegalArgumentException: value cannot be negative
...
It's defines fields and parameters with the same names "value", "name".
You can add modifiers such as private ...
In the case of case classes it should be:
case class NonNegativeDouble(private val initValue: Double) {
val value = Math.abs(initValue)
def copy(value: Double = this.value) = NonNegativeDouble(value)
}
The implementation of copy is required to prevent the sintesized version of the compiler that will bind the initValue argument.
I expect that the compiler is smart enough to not retain the «extra space» for the initValue. I haven't verified this behaviour.