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
Related
I was trying to look into trait and object in scala when it seems like we can use trait and object to do a similar task.
What should be the guiding principles on when to use trait and when to use object?
Edit:
As many of you are asking for an example
object PercentileStats {
def addPercentile(df: DataFrame): DataFrame // implementation
}
trait PercentileStats {
def addPercentile(df: DataFrame): DataFrame // implementation
}
There is a Process class which can use the object
object Process {
def doSomething(df: DataFrame): DataFrame {
PercentileStats.addPercentile(df)
}
}
We can also make it use the trait
object Process with PercentileStats {
def doSomething(df: DataFrame): DataFrame {
addPercentile(df)
}
}
I think the real question here is Where do I put stand-alone functions?
There are three options.
In the package
You can put stand-alone functions in the outer package scope. This makes them immediately available to the whole package but the name has to be meaningful across the whole package.
def addPercentile(df: DataFrame): DataFrame // implementation
In an object
You can group stand-alone functions in an object to provide a simple namespace. This means that you have to use the name of the object to access the functions, but it keeps them out of the global namespace and allows the names to be simpler:
object PercentileStats {
def add(df: DataFrame): DataFrame // implementation
}
In a trait
You can group stand-alone functions in a trait. This also removes them from the package namespace, but allows them to be accessed without a qualifier from classes that have that trait. But this also makes the method visible outside the class, and allows them to be overridden. To avoid this you should mark them protected final:
trait PercentileStats {
protected final def addPercentile(df: DataFrame): DataFrame // implementation
}
Which is best?
The choice really depends on how the function will be used. If a function is only to be used in a particular scope then it might make sense to put it in a trait, otherwise the other options are better. If there are a number of related function then grouping them in an object makes sense. One-off functions for general use can just go in the package.
Object - is a class that has exactly one instance. It is created lazily when it is referenced, like a lazy val.
As a top-level value, an object is a singleton.
Traits - are used to share interfaces and fields between classes.
Classes and objects can extend while traits cannot be instantiated and therefore have no parameters.
So, it means that if you prefer singleton type implementation with no new instance happen then use Object but if you want to inherit implementation to other class or objects then you can use trait.
Traits: are equivalent to interfaces in Java. So you can use it to define public contracts like interfaces in Java. In addition, a trait can be used to share values (beside methods) between classes extends the trait.
Objects in Scala is actually quite flexible. Example use cases include:
singletons: If you think that your objects are singletons (exactly
one instance exists in the program), you can use object.
factory: for instance, companion object of a class can be used as factory for creating instances of the class.
to share static methods: for example, common utilities can be declared in one object.
You also have to consider how you would want to use / import it.
trait Foo {
def test(): String
}
object Bar extends Foo
import Bar._
Objects enable you to import rather than mix in your class.
It is a life saver when you want to mock - with scalamock - a class that mixes a lot of traits and expose more than 22 methods that you don't really need exposed in the scope.
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 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.
Just looking at Scala Akka and wondering what is the difference between the following object initialisation methods.
system.actorOf(Props[HelloActor], name = "helloactor")
and
system.actorOf(Props(new HelloActor("Fred")), name = "helloactor")
I can understand the second one, Props(new HelloActor()), but what is the first one, Props[HelloActor]? I don't know its name so can't google for it.
Props is a case class with a companion object. In Scala code you will see two major ways people will construct objects. One is with a constructor on a class. Another major way is by calling an apply() method on a companion object.
If you look at the source code of akka.actor.Props you will notice that the companion object has four apply() methods, two of which you are referencing in your code above. At time of writing their signatures are:
def apply[T <: Actor: ClassTag](): Props
def apply[T <: Actor: ClassTag](creator: ⇒ T): Props
As helpful sugar Scala allows you to call an apply method without stating the apply method so in your first example you can rewrite that as Props[HelloActor]() and the compiler inserts the apply() method for you. Next, if a method has no arguments you may omit the parenthesis. So the call becomes Props[HelloActor] as you have pointed out above.
Your second example calls the second apply() method.
As to your question about how does the real HelloActor class get instantiated that is a little more complicated. All of the explicitly defined apply() methods eventually call a special apply() method that is generated by the nature of Props being a case class. This apply calls the constructor on Props which creates an akka.actor.IndirectActorProducer. This class holds many strategies that can be used to instantiate the actor. In your simple case it eventually uses reflection to construct your actor.
Square brackets [] in Scala denote the use of a generic class. Generic classes are classes which take a type as a parameter. The class name between the brackets in the instantiation of a generic class is the argument for that type parameter.
So in your case, the Props class has 1 generic parameter, and the line Props[HelloActor] is providing the type HelloActor as the argument for that generic parameter.
I understand that using something like
case class private A()
new A()#This will be a invalid call as A is private
But what I do not understand that as from an implementation perspective, what advantage does this provide while coding? Because calling A() twice will give 2 instances of the class anyways. If this syntax is not used to prevent instantiation like Java, then why would I want to not let someone instantiate my class using new?
Marking a case class constructor private is useless. As you've notices, case classes get a synthetic companion object with an apply method whose implementation is simply a call to the actual constructor.
Scala case classes have been designed to just "classes + the case modifier", meaning that everything that works on classes also works on case classes, which also include the (pointless) ability to specify access modifiers on the constructor.