"new" keyword in Scala - scala

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).

Related

Get static methods of a class nested in an object using Java reflection

I want to get the list of methods in a nested companion object using Java reflection. This is A.B in the example below.
object A {
object B {
def foo: Int = 4
}
class B {}
def bar: Int = 5
}
class A {}
// This works, `bar` is printed.
println(classOf[A].getMethods.map(_.getName).mkString("\n"))
// This doesn't work, `foo` is not printed.
println(classOf[A.B].getMethods.map(_.getName).mkString("\n"))
Seems like getting the list of methods on the outer companion object A works, but not on the nested one.
Is there any way to write a method that would take a Class[_] and get all the methods defined on the companion object whether it's nested or not?
classOf[A] and classOf[A.B] are not the classes of the companion objects, so they don't have these methods. A.type and B.type sortof are but they aren't class types in Scala. As pedrofurla points out, you can do this to reach them as java Class objects:
scala> A.getClass.getDeclaredMethods
res17: Array[java.lang.reflect.Method] = Array(public int A$.bar())
scala> A.B.getClass.getDeclaredMethods
res18: Array[java.lang.reflect.Method] = Array(public int A$B$.foo())
I came up with the following code, which makes an assumption that the companion's class name can be determined by appending $ to the class name.
This allows calling a method on the companion given the class of a corresponding type, regardless of whether the companion is nested or not:
def getCompanion(clazz: Class[_]) = {
Class.forName(clazz.getName + "$").getField("MODULE$").get(())
}
def companionMethod(clazz: Class[_], methodName: String) = {
getCompanion(clazz).getClass.getMethod(methodName).invoke(companion)
}
// Print all companion methods:
println(getCompanion(classOf[A.B]).getMethods.map(_.getName).mkString("\n"))
println(companionMethod(classOf[A], "bar") == 5)
println(companionMethod(classOf[A.B], "foo") == 4)

Two ways of (kind of) instantiating a trait in Scala

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).

Restrict Construction of Scala Class

Given:
class Foo(x: Int) {}
object Foo {
def apply(x: Int) = new Foo(x)
}
Besides marking Foo's constructor as private, how can I present a warning or compile-time failure when calling new Foo(...)?
In other words, I'd like to restrict (either by compile-time warning or error) construction of Foo to Foo.apply.
Is this possible?
In scala there are two idiomatic ways how to achieve that.
Constructor private to the class and companion object.
Factory has access to constructor, while anyone else doesn't:
class Foo private[Foo](val x: Int)
object Foo {
def apply(x:Int) = new Foo(x)
}
val foo = new Foo(1) // cannot compile
val foo1 = Foo(1) //compiles fine
Sealed abstract class.
In scala sealed class can be extended only in the same source file it is defined.
I suggest to make Foo sealed abstract class and return anonymous child of Foo in object's apply method.
sealed abstract class Foo(val x:Int)
object Foo {
def apply(x:Int):Foo = new Foo(x) {}
}
In this case Foo can be created nowhere except the file where it is defined.
UPD: Actually, this question was already discussed on stackoverflow.
UPD2: Added brief overview of both methods.

Avoid an overridden `val` being initialised in the base trait?

In the following code:
trait Base {
val foo: String = {
println("Hi, I'm initializing foo in trait Base")
"foo"
}
}
class Overrider extends Base {
override val foo = "bar!"
}
object Runner extends App {
println(new Overrider().foo)
println((new {override val foo = "baz"} with Base).foo)
}
Base trait's foo value initialisation is called regardless of whether I override the val by extending the trait or using an early initialiser:
Hi, I'm initializing foo in trait Base
bar!
Hi, I'm initializing foo in trait Base
baz
Is there a way to use vals and avoid that happening or should I just stick with lazy vals?
Either use lazy val as you mentioned or def. AFAIK there is no other way to avoid the initialization of vals in base classes. This is because everything outside class member definitions goes into the constructor. Therefore vals will be initialized on construction time.
Another approach would be to define an interface which you extend from:
trait Base {
def foo: String
}
class Foo extends Base {
override val foo = "foo"
}
class Bar extends Base {
override val foo = "bar"
}
As other users answered to your question, you have to define foo as a def if you do not want the Base trait method being valuated.
You told to me in the comments of your question that you were trying to implement a wiring module, as the one described in this link. Then, you're basically trying to implement the thin cake pattern.
In this case, it is not logically correct to declare foo as a val. foo represents a dependency that cannot be eagerly resolved . If you use a val, the two components will be tight coupled. You've to define foo as a def to let to your main application (or test) to wire foo to the correct type, i.e. a concrete class or a mock.
Let me know if you want some more explanations.

is there any way to use import someValue._ to implement overriding methods in scala?

Is there any way to do anything like this:
scala> trait Foo { def f:Int=0 }
defined trait Foo
scala> class FooImpl extends Foo { override val f = 1 }
defined class FooImpl
scala> class Bar(foo:Foo) extends Foo{ import foo._ }
defined class Bar
scala> (new Bar(new FooImpl)).f
res2: Int = 0
scala> trait Foo { def f:Int }
defined trait Foo
scala> class Bar(foo:Foo) extends Foo{ import foo._ }
<console>:8: error: class Bar needs to be abstract, since method f in trait Foo of type => Int is not defined
class Bar(foo:Foo) extends Foo{ import foo._ }
^
scala>
...in a way that would result in a subclass overriding a parent method via import? Basically I think it would be interesting to be able to use composition without all the typing. Just curious if anything like this is possible.
What you are really asking for is a way to delegate method implementations to a member.
That issue has already been addressed here: Proxies / delegates in Scala
Basically, there is a way to do it using macros. An implementation can be found here: https://github.com/adamw/scala-macro-aop
The above provides a #delegate macro annotation that can be applied to a data member to cause the compiler to generate code to delegate method calls to that member. Note that macro annotations are an experimental feature planned for Scala 2.11, but you can use them with Scala 2.10 using the Macro Paradise compiler plugin.
Self-typing can help here (depending on exactly how you will be working with these classes - this isn't composition of instances, more composition of types):
trait Foo { def f:Int }
trait FooImpl extends Foo { override val f = 1 } // Needs to be a trait to be mixed in.
class Bar {
this: Foo => // This requires that any Bar instance must mix in a Foo (must 'be' a Foo)
}
Then you can instantiate and use your Bar instance similar to the following:
scala> (new Bar with FooImpl).f
res1: Int = 1