I know that Scala List can be created as :
val l = List(1,2,3)
What goes on under the hood when the above statement is executed ?
Is the apply method called here ?
Per the scala documentation : For sequences, apply is positional indexing
http://docs.scala-lang.org/overviews/collections/seqs.html
So , are there 2 apply methods , one for positional indexing & another as the factory method for object creation ?
This invocation actually calls the apply method on the companion object to the List class.
Many scala classes have a companion object, which is a singleton object with the same name as the class. Defining methods on this companion object, is the scala equivalent of java's static methods. It is very common for these companion objects to have one or more apply methods that are used as constructor/factory functions to create an instance of the class. In this case the List object has a method that takes a variable number of arguments of the same type, and creates a List of those objects.
In fact, if you define a case class, scala will automatically define a companion object that, among other things, includes and apply method that takes the same arguments as the case class's constructor, which is why you don't need to use new when constructing case classes.
The list instance also has an apply method, which is used to index into the list, but since it is defined on the List class it only applies to instances of the class, not the object List itself.
Related
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).
I am a little bit confused using companion objects in scala. When you want to provide multiple constructors, usually you declare a companion object and overload the apply method. But what is the difference between this two ways of doing it?:
case class Node(....)
object Node {
def apply(...) = new Node(....) // 1 way
def apply(...) = Node(...) // second way
}
Almost all examples I've seen use the first form:
When to use companion object factory versus the new keyword
"new" keyword in Scala
http://alvinalexander.com/scala/how-to-create-scala-object-instances-without-new-apply-case-class
But my code seems to work the same using both forms. Does using new keyword only have sense when we have a normal class? (Not a case class)?
When you call
val n = Node(..)
The compiler will expand the code to a Node.apply call. Now, one of these apply methods will internally have to call new in order to create an instance of the type. Case classes provide companion objects with an apply method for you out of the box to allow the shorter syntax.
When you want to provide multiple constructors, usually you declare a companion object and overload the apply method
This is the case for case classes. You can also provide additional auxiliary constructors using this():
class Foo(i: Int) {
def this() {
this(0)
}
}
Note this will not provide the syntax sugar apply does, you'll need to use new.
When you declare a case class. A companion object is generated by the compiler with apply method in it whose implementation creates the object of the case class using new keyword.
So you need not create a companion object again with apply method creating object of the case class using new keyword. This work will be done by the compiler
I just learned Scala.
When I read official documentation to look up Array, for example, it has two versions. One is for Class, the other is for Object. I think I know the difference between Class and Object and when I need find methods of Array, I usually go to the Class version. I do not quite know when I need to go to this Object version.It seems when I want to create Multidimensional arrays, I need method(ofDim) in Object version instead of class version. Why?
The identifier Array refers to either the type or its companion object, depending on context.
scala> Array('a', 'b', 'c')
res0: Array[Char] = Array(a, b, c)
res0 is an instance of the Array type. res0 is an object.
scala> Array
res1: Array.type = scala.Array$#1a69136
res1 is the companion object. res1 is an object. It is a singleton, meaning that there are no other objects of its type.
These two objects have different methods on them, because they're very different things.
Instances of the Array type have the methods defined by the class. These are, naturally, the methods that operate on a particular Array instance. For example, the length method returns the length of the array. You need an instance to do this. It wouldn't make sense to write Array.length because that doesn't specify which array you want the length of. But Array('a', 'b', 'c').length is 3.
The companion object has the methods defined by the object. These are the methods that do not require an Array instance. Companion objects will object contain methods that create instances, as is the case for Array. Hence Array.ofDim(2, 2) creates a 2x2 array. That method isn't defined by the class because instances shouldn't have it. For example, it wouldn't make much sense to write Array('a', 'b', 'c').ofDim(2, 2), because the result (an empty 2x2 array) would have nothing to do with the instance that the method was called upon.
As per my understanding, the class defines the actual implementation with methods to operate on the instances (in this case Array - methods like map, count, fold etc.).
The companion object on the other hand provides utility methods for creation (like apply...) (for Array in this case it mostly contains factory methods).
The class methods operate on the class instance data. Like elements of an array for the Array class. The companion object methods usually operate on multiple instances of a class or create one.
The companion objects in Scala play the same role as static members in Java or C#. For example, for Array it mostly contain factory methods. I would not expect to see methods like length or isEmpty on the companion object and on the other hand I would expect to see factory methods on the instance of a class.
I'm very confused by Scala's HashSet and Set types as they both seem to do the same thing.
What is the difference between them?
Is it the same in Java?
In my reference it says that HashSet is an "explicit set class" (as compared to Set). What does that mean?
Scala's mutable and immutable HashSet implementations are concrete classes which you can instantiate. For example, if you explicitly ask for a new scala.collection.immutable.HashSet, you will always get a set which is implemented by a hash trie. There are other set implementations, such as ListSet, which uses a list.
Set is a trait which all the set implementations extend (whereas in Java, Set is an interface).
Set is also a companion object* with an apply** method. When you call Set(...), you're calling this factory method and getting a return value which is some kind of Set. It might be a HashSet, but could be some other implementation. According to 2, the default implementation for an immutable set has special representation for empty set and sets size up to 4. Immutable sets size 5 and above and mutable sets all use hashSet.
*In Scala, instead of having static class methods, you can create a singleton object with the same name as your class or trait. This is called a companion object, and methods you define on it can be called as ObjectName.method(), similar to how you'd call a static method in Java.
**Set(x) is syntactic sugar for Set.apply(x).
I want to write class whose constructor takes two parameters, but the arguments are not actually members of the class. e.g.
class P(V1:Int, V2:Int) {
val set = Set(V1, V2)
}
Having constructed the 'set', I don't actually care about V1 and V2. Is there a way of expressing this in Scala ?
Well, exactly like that. If the constructor arguments are not tagged with val or var, nor the class is a case class, then they'll be kept allocated if used inside methods (or lazy val, I suppose). If used just in the constructor, they won't be allocated with the object, not even as private fields.