Scala Case Classes - Are they just structs? - scala

So I just learned about scala case classes, and I'm told they are used to provide a simple wrapper around a bunch of properties so that it's easier to test for equality. But now I have two questions:
Is this just the same thing as a struct in C++/C#?
Are case classes a value type or a reference type?

First note that a struct in C++ and a struct in C# are very different things.
Structures in C++ are just like regular classes but by default, their members
are public. See this post for more on this topic.
Structures in C# are value types. When passed as a parameter, they are
copied instead of passed via a pointer. This behaviour is similar to a
primitive type in Java. This behaviour is the default in C++, with any
class or struct.
Your second question has been answered in Eric's answer but the important point is that C# structures are passed completely by value (all their fields are copied) while Java/C# classes are passed via a pointer (that is passed by value). See this famous post if you want the full explanation.
Unfortunately, it is not currently possible to have a true value type in JVM bytecode. You cannot make your own type that will be fully copied everytime you pass it. And the answer is no, case classes aren't value types like C# structures. A JVM language may try to replicate the behaviour of a value type but it will be managed by the GC and passed via a pointer (that is passed by value).
To give a more direct answer, no:
Case classes are like regular classes with a few key differences.
Learn more about them on this page.

Not really. What scala case classes are most like is ... scala classes.
They actually are regular scala classes with a few additional methods, that get added to them automatically - namely, .copy on the class itself and .apply and .unapply on the companion object. They also get a nice .toString method, listing all the fields, and .equals, that compares instance members rather than the object ref.
In most other respects, they are just regular scala classes.

Scala classes are just like Java classes. Their reference is passed by value.
Scala case classes are just like scala classes, but some things are automatically generated for you:
The fields of the constructor are publicly accessible (albeit a case class is immutable by default, thus you can regard them as public final values in Java, unless you declare the fields of the case class as var)
An equals and hashCode method based on the fields of the constructor
An apply and unapply method in the companion object
A toString method showing all the values of the constructor
A copy method
Here's an example:
case class MasterOfTheUniverse(name: String, power: Int)
scala> MasterOfTheUniverse("He-Man", 100).name
res1: String = He-Man
scala> MasterOfTheUniverse("He-Man", 100).power
res2: Int = 100
scala> MasterOfTheUniverse("He-Man", 100).toString
res3: String = MasterOfTheUniverse(He-Man,100)
scala> MasterOfTheUniverse("He-Man", 100) == MasterOfTheUniverse("She-Ra", 90)
res4: Boolean = false
scala> MasterOfTheUniverse("She-Ra", 90) == MasterOfTheUniverse("She-Ra", 90)
res6: Boolean = true
scala> MasterOfTheUniverse("He-Man", 100).copy(name = "He-Manatee")
res7: MasterOfTheUniverse = MasterOfTheUniverse(He-Manatee,100)

Related

How are primitives types objects in Scala?

How are primitive types in Scala objects if we do not use the word "new" to instantiate the instances of those primitives? Programming in Scala by Martin Odersky described the reasoning as some enforcing by a "trick" that makes these value classes to be defined abstract and final, which did not quite make sense to me because how are we able to make an instance of these classes if its abstract? If that same primitive literal is to be stored somewhere let's say into a variable will that make the variable an object?
I assume that you use scala 2.13 with implementation of literal types. For this explanation you can think of type and class as synonyms, but in reality they are different concepts.
To put it all together it worth to treat each primitive type as a set of subtypes each of which representing type of one single literal value.
So literal 1 is a value and type at the same time (instance 1 of type 1), and it is subtype of value class Int.
Let's prove that 1 is subtype of Int by using 'implicitly':
implicitly[1 <:< Int] // compiles
The same but using val:
val one:1 = 1
implicitly[one.type <:< Int] // compiles
So one is kind of an instance (object) of type 1 (and instance of type Int at the same time because because Int is supertype of 1). You can use this value the same way as any other objects (pass it to function or assign to other vals etc).
val one:1 = 1
val oneMore: 1 = one
val oneMoreGeneric: Int = one
val oneNew:1 = 1
We can assume that all these vals contain the same instance of one single object because from practical perspective it doesn't actually matter if this is the same object or not.
Technically it's not an object at all, because primitives came form java (JVM) world where primitives are not objects. They are different kind of entities.
Scala language is trying to unify these two concepts into one (everything is classes), so developers don't have to think too much about differences.
But here are still some differences in a backstage. Each value class is a subtype of AnyVal, but the rest of the classes are subtype of AnyRef (regular class).
implicitly[1 <:< AnyVal] //compiles
implicitly[Int <:< AnyVal] // compiles
trait AnyTraint
implicitly[AnyTraint <:< AnyVal] // fails to compail
implicitly[AnyTraint <:< AnyRef] // compiles
And in addition, because of its non-class nature in the JVM, you can't extend value classes as regular class or use new to create an instance (because scala compiler emulates new by itself). That's why from perspective of extending value classes you should think about them as final and from perspective of creating instances manually you should think of them as abstract. But form most of the other perspectives it's like any other regular class.
So scala compiler can kind of extend Int by 1,2,3 .. types and create instances of them for vals, but developers can't do it manually.

class Int is abstract; cannot be instantiated

While going through Programming in Scala, i came across:
While you can define your own value classes (see Section 11.4), there
are nine value classes built into Scala: Byte, Short, Char, Int, Long,
Float, Double, Boolean, and Unit. The first eight of these correspond
to Java's primitive types, and their values are represented at run
time as Java's primitive values. The instances of these classes are
all written as literals in Scala. For example, 42 is an instance of
Int, 'x' is an instance of Char, and false an instance ofBoolean. You
cannot create instances of these classes using new. This is enforced
by the "trick" that value classes are all defined to be both abstract
and final.
Due to which new Int gives the error class Int is abstract; cannot be instantiated
val a: Int = new Int in Scala. Java allows new Integer(23).
Question: What is the trick the author is taking about. Why Scala defines value classes to be abstract and final.
What is the trick the author is taking about ?
The "trick" is that
when a class is abstract, you cannot make instances of it (cannot call new).
when a class is final, you cannot make subclasses
when a class is abstract and you cannot make subclasses, then you also cannot make a concrete subclass that you could instantiate
So as a result, value classes cannot be instantiated by application code.
Why Scala defines value classes to be abstract and final.
The point of value classes is that they are defined by their (immutable) value/contents. The object identity is not relevant.
The Scala compiler also tries to optimize value classes by not creating any objects at all where possible (just using unboxed primitives directly). That only works if we can be sure that you can just box and unbox at will.
In Java new Integer(1) and another new Integer(1) are two different objects, but that is not useful for a pure value class (if you want to use these different instances as lock monitor objects or something else where you need object identity, you are just confusing yourself and others and should not have used Integer).

Quick Documentation For Scala Apply Constructor Pattern in IntelliJ IDE

I am wondering if there is a way to get the quick documentation in IntelliJ to work for the class construction pattern many scala developers use below.
SomeClass(Param1,Parma2)
instead of
new SomeClass(param1,Param2)
The direct constructor call made with new obviously works but many scala devs use apply to construct objects. When that pattern is used the Intelij documentation look up fails to find any information on the class.
I don't know if there are documents in IntelliJ per se. However, the pattern is fairly easy to explain.
There's a pattern in Java code for having static factory methods (this is a specialization of the Gang of Four Factory Method Pattern), often along the lines of (translated to Scala-ish):
object Foo {
def barInstance(args...): Bar = ???
}
The main benefit of doing this is that the factory controls object instantiation, in particular:
the particular runtime class to instantiate, possibly based on the arguments to the factory. For example, the generic immutable collections in Scala have factory methods which may create optimized small collections if they're created with a sufficiently small amount of contents. An example of this is a sequence of length 1 can be implemented with basically no overhead with a single field referring to the object and a lookup that checks if the offset is 0 and either throws or returns its sole field.
whether an instance is created. One can cache arguments to the factory and memoize or "hashcons" the created objects, or precreate the most common instances and hand them out repeatedly.
A further benefit is that the factory is a function, while new is an operator, which allows the factory to be passed around:
class Foo(x: Int)
object Foo {
def instance(x: Int) = new Foo(x)
}
Seq(1, 2, 3).map(x => Foo(x)) // results in Seq(Foo(1), Foo(2), Foo(3))
In Scala, this is combined with the fact that the language allows any object which defines an apply method to be used syntactically as a function (even if it doesn't extend Function, which would allow the object to be passed around as if it's a function) and with the "companion object" to a class (which incorporates the things that in Java would be static in the class) to get something like:
class Foo(constructor_args...)
object Foo {
def apply(args...): Foo = ???
}
Which can be used like:
Foo(...)
For a case class, the Scala compiler automatically generates a companion object with certain behaviors, one of which is an apply with the same arguments as the constructor (other behaviors include contract-obeying hashCode and equals as well as an unapply method to allow for pattern matching).

why scala value class#toString contains case class info?

value classes can be used to achieve type safety without the overhead of unboxing.
I had the impression that in runtime such types/classes would "not exist", being seen as simple types (for instance, a value class case class X(i: Int) extends AnyVal would be a simple Int on runtime).
But if you do call a .toString method on a value class instance it would print something like:
scala> val myValueClass = X(3)
myValueClass: X = 3
scala> myValueClass.toString
res5: String = X(3)
so I guess the compiler includes some information after all?
Not really. The compiler creates a static method (in Scala this corresponds to the class's companion object) which is called with your int value as a parameter in order to simulate calling a method on your value class-typed object.
Your value class itself only exists in the source code. In compiled bytecode an actual primitive int is used and static methods are called rather than new object instances with real method calls. You can read more about this mechanism here.
Value classes are designed so that adding or removing extends AnyVal (if legal) shouldn't change the results of calculations (except even non-case value classes have equals and hashCode defined automatically like case classes). This requires that in some circumstances they survive, e.g.
def toString(x: Any) = x.toString
toString(myValueClass)
but the situation in your question isn't one of them.
http://docs.scala-lang.org/sips/completed/value-classes.html#expansion-of-value-classes explains more precisely how value classes are implemented and is useful to see in what cases they survive, though some details may have changed since.

Using private constructor in a macro

I want to use a private constructor in a macro. This example is a positive integer, but the basic pattern could not only be used for other numeric types like even numbers, but also string derived types like email addresses or a directory name. By making the constructor private the user is denied the opportunity to make an illegal type. I have the following code:
object PosInt
{
import language.experimental.macros
import reflect.runtime.universe._
import reflect.macros.Context
def op(inp: Int): Option[PosInt] = if (inp > 0) Some(new PosInt(inp)) else None
def apply(param: Int): PosInt = macro apply_impl
def apply_impl(c: Context)(param: c.Expr[Int]): c.Expr[PosInt] =
{
import c.universe._
param match {
case Expr(Literal(i)) if (i.value.asInstanceOf[Int] > 0) =>
case Expr(Literal(i)) if (i.value.asInstanceOf[Int] == 0) => c.abort(c.enclosingPosition, "0 is not a positive integer")
case Expr(Literal(i)) => c.abort(c.enclosingPosition, "is not a positive integer")
case _ => c.abort(c.enclosingPosition, "Not a Literal")
}
reify{new PosInt(param.splice)}
}
}
class PosInt (val value: Int) extends AnyVal
However if I make the PosInt Constructor private, although the Macro compiles as expected I get an error if try to use the macro. I can't work out how to build the expression tree manually, but I'm not sure if that would help anyway. Is there anyway I can do this?
You still can't use a private constructor even if PosInt is not a value class. I'll accept an answer that doesn't use a value class. The disadvantage of value classes is that they get type erasure. Plus classes that I'm interested in like subsets of 2d co-ordinates can't be implement as value classes anyway. I'm not actually interested in Positive Integers, I'm just using them as a simple test bed. I'm using Scala 2.11M5. Scala 2.11 will have the addition of the quasiquotes feature. I haven't worked out how to use, quasiquotes yet, as all the material at the moment on them seems to assume a familiarity with Macro Paradise, which I don't have.
Unfortunately for what you are trying to achieve, macros do not work this way. They just manipulate the AST at compile time. Whatever the final result is, it is always something you could have written literally in Scala (without the macro).
Thus, in order to constrain the possible values of PosInt, you will need a runtime check somewhere, either in a public constructor or in a factory method on the companion object.
If runtime exceptions are not palatable to you, then one possible approach would be:
Make the constructor private on the class.
Provide (for example) a create method on the companion object that returns Option[PosInt] (or Try[PosInt], or some other type of your choice that allows you to express a "failure" when the argument is out of range).
Provide an apply method on the companion object similar to your example, which verifies at compile time that the argument is in range and then returns an expression tree that simply calls create(x).get.
Calling .get on the Option is acceptable in this case because you are sure that it will never be None.
The downside is that you have to repeat the check twice: once at compile time, and once at runtime.
I'm not an expert, but I figured I'll give it a shot...
In Java, the scope of a private constructor is limited to the same class... so the PosInt object would need to be moved into the scope of the same class from which it's being called.
With that said, I found an article that shows two ways you can keep the object from being inherited # http://www.developer.com/java/other/article.php/3109251/Stopping-Your-Class-from-Being-Inherited-in-Java-the-Official-Way-and-the-Unofficial-Way.htm
It describes using the "final" keyword in the class declaration to prevent it from being inherited. That's the "official" way. The "unofficial" way is to make the constructor private, but add a public static method that returns an object of the class...
Yes, I know, it is an old question... but it was left unanswered. You never know when an old question will be the top hit in someone's search results...