scala: Any default apply method in a class? - scala

Does scala provide a default apply method for a class?
I have a class:
class Player(tea: String, sal: Int = 0) {
val team = tea
private val salary = sal
}
So no apply method here, and I haven't defined any companion object for it, so no apply method from there too.
But I am able to do:
val player = Player("AAAA", 1000)
With no 'new' operator used, I understand that this line of code must invoke some apply method. But there is none defined by me. So how does it work?

Yes, since Scala 3, as described in the docs:
Scala case classes generate apply methods, so that values of case classes can be created using simple function application, without needing to write new.
Scala 3 generalizes this scheme to all concrete classes. Example:
class StringBuilder(s: String):
def this() = this("")
StringBuilder("abc") // old: new StringBuilder("abc")
StringBuilder() // old: new StringBuilder()
This works since a companion object with two apply methods is generated together with the class. The object looks like this:
object StringBuilder:
inline def apply(s: String): StringBuilder = new StringBuilder(s)
inline def apply(): StringBuilder = new StringBuilder()
The synthetic object StringBuilder and its apply methods are called constructor proxies. Constructor proxies are generated even for Java classes and classes coming from Scala 2. The precise rules are as follows:
A constructor proxy companion object object C is created for a concrete class C, provided the class does not have already a companion, and there is also no other value or method named C defined or inherited in the scope where C is defined.
Constructor proxy apply methods are generated for a concrete class provided
the class has a companion object (which might have been generated in step 1), and
that companion object does not already define a member named apply.
Each generated apply method forwards to one constructor of the class. It has the same type and value parameters as the constructor.

Related

Why can I create new Random without the keyword "new"

In my study of Scala I ran into the following snippet:
val r = Random
Now from my understanding from Alvin Alexander's excellent post (How to create Scala object instances without using the “new” keyword (apply) you can create a new Scala object instance without using the new keyword as follows:
Create a companion object for your class, and define an apply method
in the companion object with the desired constructor signature.
Define your class as a “case class.”
However, when I look at the source code for the Random class (Scala 2.12.8) I see that it is not a case class nor does the companion object have the apply method in its companion object.
Could someone please explain to me why it's valid syntax to create a Random as posted above even though it doesn't meet the requirements as described in Alvin Alexander's post?
Thanks!
In this context Random is a singleton instance of class Random
object Random extends Random
where
class Random(val self: java.util.Random) extends ... {
...
def this() = this(new java.util.Random())
...
}
hence it is already a value. For example consider the following
class Foo(val v: Int)
object Foo extends Foo(42)
Foo.v
which outputs
res0: Int = 42
Note how Foo in Foo.v is already referencing an instance singleton value of class Foo. Hence r in
val r = Random
is simply referencing existing singleton value. It is akin to
val a = 11
val r = a
Simply put: you are not creating a new instance of the Random class, you are assigning the existing instance of the Random class which also happens to be called Random to the field r.
It might sound confusing that there is both a class and an object named Random but there actually cannot possibly be any confusion, since in Scala, types and terms live in different "worlds" and their names can never mix.
Note that it is in fact quite common to have a class or trait and an object with the same name, for the following reason:
if an object has the same name as a class or trait, and
that object is defined in the same scope as the class or trait with the same name, and
that object is defined in the same compilation unit as the class or trait with the same name, then
that object is called a companion module and has privileged access to the internals of the class or trait.

Anonynomus derivation from T in generic function [duplicate]

I'm trying to create an instance of a trait using this method
val inst = new Object with MyTrait
This works well, but I'd like to move this creation in to a generator function, ie.
object Creator {
def create[T] : T = new Object with T
}
I'm obviously going to need the manifest to somehow fix the type erasure problems, but before I get to this, I run in to 2 questions :
Even with an implicit manifest, Scala still demands that T be a trait. How do I add a restriction to create[T] so that T is a trait?
If I chose to use the Class.newInstance method to create the instance dynamically rather than using "new", how would I specify the "with" in "new Object with T"? Is it possible to dynamically create new concrete mixin types at runtime?
I'm not sure what the motivation is for your question, but you could consider passing a factory for T as an implicit parameter. This is known as using type classes or ad-hoc polymorphism.
object Test extends Application {
trait Factory[T] {
def apply: T
}
object Factory {
/**
* Construct a factory for type `T` that creates a new instance by
* invoking the by-name parameter `t`
*/
def apply[T](t: => T): Factory[T] = new Factory[T] {
def apply = t
}
}
// define a few traits...
trait T1
trait T2
// ...and corresponding instances of the `Factory` type class.
implicit val T1Factory: Factory[T1] = Factory(new T1{})
implicit val T2Factory: Factory[T2] = Factory(new T2{})
// Use a context bound to restrict type parameter T
// by requiring an implicit parameter of type `Factory[T]`
def create[T: Factory]: T = implicitly[Factory[T]].apply
create[T1]
create[T2]
}
At the other end of the spectrum, you could invoke the compiler at runtime, as detailed in this answer to the question "Dynamic mixin in Scala - is it possible?".
You can't do this (even with a Manifest). The code new Object with T involves creating a new anonymous class representing the combination of Object with T. To pass this to your create function, you would have to generate this new class (with new bytecode) at runtime, and Scala has no facilities for generating a new class at runtime.
One strategy might be to try to transfer the special functionality of the factory method into the class's constructor instead, and then use the constructor directly.
Another possible strategy is to create conversion functions (implicit or otherwise) to the traits you're interested in using with this class.

Understanding companion object in scala

While learning Scala, I came across interesting concept of companion object. Companion object can used to define static methods in Scala. Need few clarifications in the below Spark Scala code in regard of companion object.
class BballStatCounter extends Serializable {
val stats: StatCounter = new StatCounter()
var missing: Long = 0
def add(x: Double): BballStatCounter = {
if (x.isNaN) {
missing += 1
} else {
stats.merge(x)
}
this
}
}
object BballStatCounter extends Serializable {
def apply(x: Double) = new BballStatCounter().add(x)
}
Above code is invoked using val stat3 = stats1.map(b=>BballStatCounter(b)).
What is nature of variables stats and missing declared in the
class? Is it similar to class attributes of Python?
What is the significance of apply method in here?
Here stats and missing are class attributes and each instance of BballStatCounter will have their own copy of them just like in Python.
In Scala the method apply serves a special purpose, if any object has a method apply and if that object is used as function calling notation like Obj() then the compiler replaces that with its apply method calling, like Obj.apply() .
The apply method is generally used as a constructor in a Class Companion object.
All the collection Classes in Scala has a Companion Object with apply method, thus you are able to create a list like : List(1,2,3,4)
Thus in your above code BballStatCounter(b) will get compiled to BballStatCounter.apply(b)
stats and missing are members of the class BcStatCounter. stats is a val so it cannot be changed once it has been defined. missing is a var so it is more like a traditional variable and can be updated, as it is in the add method. Every instance of BcStatCounter will have these members. (Unlike Python, you can't add or remove members from a Scala object)
The apply method is a shortcut that makes objects look like functions. If you have an object x with an apply method, you write x(...) and the compiler will automatically convert this to x.apply(...). In this case it means that you can call BballStatCounter(1.0) and this will call the apply method on the BballStatCounter object.
Neither of these questions is really about companion objects, this is just the normal Scala class framework.
Please note the remarks in the comments about asking multiple questions.

Scala/Akka Syntax

I'm new to both Scala and Akka and have been following this tutorial. I came across the following and wondering what exactly this syntax does/mean?
import akka.actor.Props
val props1 = Props[MyActor] //Not sure what this means???
val props2 = Props(new ActorWithArgs("arg")) // careful, see below
val props3 = Props(classOf[ActorWithArgs], "arg")
I'm not sure what the line commented with //Not sure what this means does? It seems like a generic trait that gives a parameterised type. If I look at the source code, akka.actor.Props is defined as an Object that extends the trait AbstractProps. However, AbstractProps is not defined with a type parameter i.e. AbstractProps[T]. Can someone explain how that above line works and what it does?
In Scala, any object which implements an apply method can be called without the new keyword, simply by calling MyObject(), which will automatically lookup for it's apply.
If you look at the companion object for Props, you'll see the following method defined:
/**
* Scala API: Returns a Props that has default values except for "creator"
* which will be a function that creates an instance
* of the supplied type using the default constructor.
*/
def apply[T <: Actor: ClassTag](): Props =
apply(defaultDeploy, implicitly[ClassTag[T]].runtimeClass, List.empty)
This apply takes one type parameter and no arguments. T <: Actor means that T, the type you're passing, must extend Actor. That's how Scala knows how to create the object.
Additionally, any method with arity-0 in Scala may drop it's parenthesis. That's how you're seeing Props[MyActor] actually compile, as it is equivalent of Props[MyActor](), which is equivalent to Props.apply[MyActor]().
akka.actor.Props is defined as an Object that extends the trait
AbstractProps
Its also defined as a case class:
final case class Props(deploy: Deploy, clazz: Class[_], args: immutable.Seq[Any])
This is a common pattern in Scala, a class with a companion object. The companion object frequently houses factory methods, and thats what your actually calling in your example.
val props1 = Props[MyActor]
This simply calls apply() of the companion object. You can omit the parentheses in Scala if no arguments are neccessary and apply is a special method that can be invoked directly on the object/instance. Say you have a sequence and want the element at index 1:
val s = Seq("one", "two", "three")
// These two are equivalent
s(1) // -> "two"
s.apply(1) // -> "two"
Ultimately your code can be rewritten as
val props1 = Props.apply[MyActor]()

How do I create an instance of a trait in a generic method in scala?

I'm trying to create an instance of a trait using this method
val inst = new Object with MyTrait
This works well, but I'd like to move this creation in to a generator function, ie.
object Creator {
def create[T] : T = new Object with T
}
I'm obviously going to need the manifest to somehow fix the type erasure problems, but before I get to this, I run in to 2 questions :
Even with an implicit manifest, Scala still demands that T be a trait. How do I add a restriction to create[T] so that T is a trait?
If I chose to use the Class.newInstance method to create the instance dynamically rather than using "new", how would I specify the "with" in "new Object with T"? Is it possible to dynamically create new concrete mixin types at runtime?
I'm not sure what the motivation is for your question, but you could consider passing a factory for T as an implicit parameter. This is known as using type classes or ad-hoc polymorphism.
object Test extends Application {
trait Factory[T] {
def apply: T
}
object Factory {
/**
* Construct a factory for type `T` that creates a new instance by
* invoking the by-name parameter `t`
*/
def apply[T](t: => T): Factory[T] = new Factory[T] {
def apply = t
}
}
// define a few traits...
trait T1
trait T2
// ...and corresponding instances of the `Factory` type class.
implicit val T1Factory: Factory[T1] = Factory(new T1{})
implicit val T2Factory: Factory[T2] = Factory(new T2{})
// Use a context bound to restrict type parameter T
// by requiring an implicit parameter of type `Factory[T]`
def create[T: Factory]: T = implicitly[Factory[T]].apply
create[T1]
create[T2]
}
At the other end of the spectrum, you could invoke the compiler at runtime, as detailed in this answer to the question "Dynamic mixin in Scala - is it possible?".
You can't do this (even with a Manifest). The code new Object with T involves creating a new anonymous class representing the combination of Object with T. To pass this to your create function, you would have to generate this new class (with new bytecode) at runtime, and Scala has no facilities for generating a new class at runtime.
One strategy might be to try to transfer the special functionality of the factory method into the class's constructor instead, and then use the constructor directly.
Another possible strategy is to create conversion functions (implicit or otherwise) to the traits you're interested in using with this class.