I know of two ways of making an anonymous class to instantiate a trait in Scala:
scala> trait SomeTrait {
| def aUsefulMethod = ()
| }
defined trait SomeTrait
scala> val instance1 = new SomeTrait{} // Method 1
instance1: SomeTrait = $anon$1#7307556f
scala> instance1.aUsefulMethod // Returns a Unit.
scala> object instance2 extends SomeTrait // Method 2
defined module instance2
scala> instance2.aUsefulMethod // Returns a Unit.
I can't think of a reason why they are not equivalent. Am I wrong?
I'm asking in part because I used to only know method 2 but now I see that method 1 is more common. So I'm wondering if I've been doing something wrong this whole time.
The first approach new Trait {} creates a new class-instance.
The second approach creates an object which is a Singleton.
One can see this in the REPL:
Define Trait
scala> trait Example {}
defined trait Example
New anonymous class
Each call to new will return a new Instance. One can see this that each object gets a new address.
scala> new Example{}
res0: Example = $anon$1#768debd
scala> new Example{}
res1: Example = $anon$1#546a03af
Object extending Trait
Here a singleton object is created once.
scala> object X extends Example
defined object X
scala> X
res2: X.type = X$#1810399e
scala> X
res3: X.type = X$#1810399e
Impact and comparison
Even if both approaches on the surface may seem similar they lead to different results.
scala> new Example{} == new Example{}
<console>:12: warning: comparing values of types Example and Example using `==' will always yield false
new Example{} == new Example{}
^
res4: Boolean = false
scala> X == X
res5: Boolean = true
Going even deeper
On the underlying structure both aproaches will lead to different *class files being generated when run on the JVM
Anonymous class
$ cat example.scala
object Example1 {
trait A
new A {}
}
$ scalac example.scala
$ ls *class
Example1$$anon$1.class Example1$A.class
Example1$.class Example1.class
$ cat example2.scala
object Example2 {
trait A
object X extends A
}
$ scalac example2.scala
$ ls *class
Example2$.class Example2$X$.class
Example2$A.class Example2.class
val instance1 = new SomeTrait{} is the same as
class X extends SomeTrait
val instance1: SomeTrait = new X
except the compiler creates the class X and gives it a name like $anon$1. If you then do val instance2 = new SomeTrait{} the compiler will notice it can reuse the same anonymous class. And object instance2 is also basically
class instance2$ extends SomeTrait {
override def toString = "instance2"
}
lazy val instance2 = new instance2$
except you can't create new instances of instance2$. So one difference is lazy instantiation: instance2 is only actually created when it's accessed (e.g. when you call instance2.aUsefulMethod), which makes a difference if the SomeTrait constructor throws an exception or has other side effects. Another is that you can use object at the top level (outside class, trait or object).
Related
I am trying to debug a scala program. I found a trait which behavior is similar to following:
trait A {
val a: Int = b
val b: Int = a
}
class B extends A
If we look at the trait there is cyclic assignment. val b is not even defined but used in definition of val a.
The above program compile successfully. Both a and b is zero. I tried to the same with variable type string and then value was null.
There is a third class that override val a similar to following
class C extends A {
override val a: Int = 10
}
Now if an instance of class C is created value a is 10 but val of b is still 0.
Finally, I checked further and instead of overriding a in the body of class, when I override it in constructor parameter similar to following:
class D(override val a: Int) extends A
val d = new D(10)
then both d.a and d.b is initialized to 10.
I wanted to understand that:
How definition of val in trait A is valid? In other words how scala interprets the val assignment in trait A
When a val that is defined in a trait is overridden in the body of a scala class what value is being used in the body of the trait if the same val is used in the trait elsewhere
The type class pattern in Scala involves defining a trait such as:
trait Show[T] {
def show(obj: T): String
}
Then you can define instantiations of this type class as such:
object Show {
implicit val string = new Show[String] {
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
def show(obj: Boolean): String = obj.toString
}
}
The advantage of defining these instantiations for basic types in the companion object is that they are automatically in scope whenever the type class is concerned (roughly).
Functionally it would appear defining the instantiation as an implicit val or an implicit object does not change much.
Is there a difference? Is one way better than the other?
There is actually more than the type names between val and object.
You know, object in Scala is something like a singleton in Java.
Maybe you thought that both string and BooleanShow are in an object not a class so they have no difference, but that's not true.
They are val and object no matter what.
Try this in Scala REPL.
trait Show[T] {
def show(obj: T): String
}
object Show {
println("!! Show created")
implicit val string = new Show[String] {
println("!! string created")
def show(obj: String): String = obj
}
implicit object BooleanShow extends Show[Boolean] {
println("!!BooleanShow created")
def show(obj: Boolean): String = obj.toString
}
}
If only the definition is done, then no printlns are executed afterwards, since Show is a singleton in effect. It's not created yet.
Next, execute Show in Scala REPL.
scala> Show
!! Show created
!! string created
res0: Show.type = Show$#35afff3b
You see, printlns in Show and Show.string were called, but the one in Show.BooleanShow was not.
You can execute Show.BooleanShow next in Scala REPL.
scala> Show.BooleanShow
!!BooleanShow created
res1: Show.BooleanShow.type = Show$BooleanShow$#18e419c5
Show.BooleanShow was initialized at last. It is a singleton, so it is lazy.
Basically, your question is the same as val and object inside a scala class? except that your val and object are defined in an object, but the linked question tries to find differences val and object defined in a class and the method in val uses reflection (but yours uses overriding, so no reflection is involved). implicit basically does not make difference in what they are.
I think you already know the difference between class and object. Further information can be found in the linked question.
Since they say always to use explicit types for implicits, prefer val over object.
Compare Why can't Scala find my typeclass instance defined implicitly in the companion object, when the typeclass is not in a dedicated source file? where it makes a difference.
Make it lazy if necessary.
Elaboration:
scala> trait T
defined trait T
scala> object X { implicitly[T] ; object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; object O extends T }
^
scala> object X { implicitly[T] ; implicit object O extends T }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T }
^
scala> object X { implicitly[O.type] ; implicit object O extends T }
defined object X
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
<console>:8: error: could not find implicit value for parameter e: T
object X { implicitly[T] ; implicit object O extends T ; implicit def y = O }
^
scala> object X { implicitly[T] ; implicit object O extends T ; implicit def y: T = O }
defined object X
The inferred type of O is the singleton type O.type.
With val x = new X { } you are creating an anonymous subclass of X, whereas with object x extends X you create a "proper" subclass. I would think that the overhead of an object is minimal, and as #applicius points out, it has proper name. Therefore I suggest to go for the object in this case.
I use very often the selfless trait pattern and I need to use "expensive" constants inside the trait:
I would like to have a single instance of these values, which might require several steps to be computed, in all my application.
However, the selfless trait pattern results in the following design:
A trait MyStuff
An object MyStuff extends MyStuff
Clearly, putting constants inside the object and using them inside a trait creates a cyclic dependency. Putting them on the trait however , makes possible for all the classes extending the trait to override them, and therefore they are certainly not an application-wide singleton.
Is the Scala compiler "clever enough" to makes final vals inside a trait become "old java public static final" ?
No, scala will not translate a final val inside a trait to the equivalent of a java static final, because the final val will need to be an instance member (not a static member) of the inheriting class.
scala> trait myStuff { final val Test="test" }
defined trait myStuff
scala> class t extends myStuff
defined class t
scala> t.Test
<console>:8: error: not found: value t
t.Test
^
// we need an instance of t to access Test
scala> new t
res2: t = t#35612600
scala> res2.Test
res3: String = test
if you're using selfless trait and you can't store your final val in MyStuff's companion object (because you're using it in the trait itself), you could probably just create another object for your final val.
//your expensive constant is here
scala> object MyConstant {final val C="C"}
defined module MyConstant
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait MyStuff {
import MyConstant._
def doStuff = C
}
object MyStuff extends MyStuff
// Exiting paste mode, now interpreting.
defined trait MyStuff
defined module MyStuff
// let's test importing the companion object of the selfless trait
scala> import MyStuff._
import MyStuff._
scala> doStuff
res4: String = C
What's an example of the cyclic dependency you're concerned about?
Usually that's solved through appropriate use of defs in the trait or lazy vals.
Here's an example issue that is induced by default args (which are synthesized in the companion object).
But if you need eagerness, you can always define early, définition en avance:
scala> :pa
// Entering paste mode (ctrl-D to finish)
trait Foo {
val v = 2 * Foo.w
}
object Foo extends {
private val w = 3
} with Foo
// Exiting paste mode, now interpreting.
defined trait Foo
defined object Foo
scala> Foo.v
res11: Int = 6
If calculating w uses members of Foo, though, you'd have to go lazy:
trait Foo {
val v = 2 * Foo.w
def x = 7
}
object Foo extends Foo {
lazy val w = 3 * x
}
This is the second time today I've needed the one-question FAQ, but I haven't looked for its new home yet.
(Edit: why, here it is.)
As analogue of public static final you should use a companion object like this:
trait MyStuff
object MyStuff {
val publicStaticFinal = ...
}
In this case scalac creates a singleton object (public static final MyStuff$ MODULE$) with method public int publicStaticFinal(). You could make this method final if you want to.
For public final - use final val:
trait MyStuff
final val publicFinal = ...
}
In this case scalac creates an interface with public abstract int publicFinal() and implements it in every ancestor of MyStuff as public final int publicFinal().
I have a very simple question - when should we apply the new keyword when creating objects in Scala? Is it when we try to instantiate Java objects only?
Use the new keyword when you want to refer to a class's own constructor:
class Foo { }
val f = new Foo
Omit new if you are referring to the companion object's apply method:
class Foo { }
object Foo {
def apply() = new Foo
}
// Both of these are legal
val f = Foo()
val f2 = new Foo
If you've made a case class:
case class Foo()
Scala secretly creates a companion object for you, turning it into this:
class Foo { }
object Foo {
def apply() = new Foo
}
So you can do
f = Foo()
Lastly, keep in mind that there's no rule that says that the companion apply
method has to be a proxy for the constructor:
class Foo { }
object Foo {
def apply() = 7
}
// These do different things
> println(new Foo)
test#5c79cc94
> println(Foo())
7
And, since you mentioned Java classes: yes -- Java classes rarely have
companion objects with an apply method, so you must use new and the actual
class's constructor.
Is it when we try to instantiate java objects only?
Not at all. There is two general cases when you ommit new in scala.
With singleton objects (that are oftenly used to store static functions and as a kind of factory similar to what you may seen in java):
scala> object LonelyGuy { def mood = "sad" }
defined module LonelyGuy
scala> LonelyGuy
res0: LonelyGuy.type = LonelyGuy$#3449a8
scala> LonelyGuy.mood
res4: java.lang.String = sad
With a case classes (actually, underneath there are class + object = companion pattern, e.g. having class and object with the same name):
scala> case class Foo(bar: String)
defined class Foo
scala> Foo("baz")
res2: Foo = Foo(baz)
So when you work with a simple classes, rules are the same as with Java.
scala> class Foo(val bar: String)
defined class Foo
scala> new Foo("baz")
res0: Foo = Foo#2ad6a0
// will be a error
scala> Foo("baz")
<console>:8: error: not found: value Foo
Foo("baz")
Bonus, there is a anonymous classes in scala, which can be constructed like this:
scala> new { val bar = "baz" }
res2: java.lang.Object{val bar: java.lang.String} = $anon$1#10ee5b8
scala> res2.bar
res3: java.lang.String = baz
Is it when we try to instantiate Java objects only?
With Scala 3 (which should be released mid 2020, eight years later), based on Dotty: never.
Scala 3 will drop "new", as in this thread
Creator applications allow to use simple function call syntax to create instances
of a class, even if there is no apply method implemented.
Example:
class StringBuilder(s: String) {
def this() = this(s)
}
StringBuilder("abc") // same as new StringBuilder("abc")
StringBuilder() // same as new StringBuilder()
Creator applications generalize a functionality provided so far only for case classes, but the mechanism how this is achieved is slightly different.
Instead of an auto-generated apply method, we add a new possible interpretation to a function call f(args).
How to programmatically determine if the given class is a case class or a simple class?
Using new Scala reflection API:
scala> class B(v: Int)
defined class B
scala> case class A(v: Int)
defined class A
scala> def isCaseClassOrWhat_?(v: Any): Boolean = {
| import reflect.runtime.universe._
| val typeMirror = runtimeMirror(v.getClass.getClassLoader)
| val instanceMirror = typeMirror.reflect(v)
| val symbol = instanceMirror.symbol
| symbol.isCaseClass
| }
isCaseClassOrWhat_$qmark: (v: Any)Boolean
scala> class CaseClassWannabe extends Product with Serializable {
| def canEqual(that: Any): Boolean = ???
| def productArity: Int = ???
| def productElement(n: Int): Any = ???
| }
defined class CaseClassWannabe
scala> isCaseClassOrWhat_?("abc")
res0: Boolean = false
scala> isCaseClassOrWhat_?(1)
res1: Boolean = false
scala> isCaseClassOrWhat_?(new B(123))
res2: Boolean = false
scala> isCaseClassOrWhat_?(A(321))
res3: Boolean = true
scala> isCaseClassOrWhat_?(new CaseClassWannabe)
res4: Boolean = false
Currently (2011), you can use reflection to find out if the class implements the interface scala.Product:
scala> def isCaseClass(o: AnyRef) = o.getClass.getInterfaces.find(_ == classOf[scala.Product]) != None
isCaseClass: (o: AnyRef)Boolean
scala> isCaseClass(Some(1))
res3: Boolean = true
scala> isCaseClass("")
res4: Boolean = false
This is just an approximation - you could go further and check if it has a copy method, if it implements Serializable, if it has a companion object with an appropriate apply or unapply method - in essence, check for all the things expected from a case class using reflection.
The scala reflection package coming in one of the next releases should make case class detection easier and more precise.
EDIT:
You can now do it using the new Scala Reflection library -- see other answer.
If you mean: Can I determine whether a class is a case class or a non-case class programmatically, the answer is no, but you can do an approximation. Case classes are just a compiler hack, they tell the compiler to create certain methods etc. In the final bytecode, there is no difference between normal classes and case classes.
From How does a case class differ from a normal class?
You can do pattern matching on it,
You can construct instances of these classes without using the new
keyword,
All constructor arguments are accessible from outside using
automatically generated accessor functions,
The toString method is automatically redefined to print the name
of the case class and all its arguments,
The equals method is automatically redefined to compare two
instances of the same case class structurally rather than by identity.
The hashCode method is automatically redefined to use the
hashCodes of constructor arguments.
So you can actually create a case class by just defining the correct methods & companion objects yourself.
For an idea as to how to find out if a class could be a case class, look at the answer from axel22.