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().
Related
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).
Given the following:
scala> trait Foo
defined trait Foo
scala> case object Bip extends Foo
defined module Bip
scala> case object Bar extends Foo
defined module Bar
Is there any feature, built into Scala, that can make a Foo from a String?
example:
f("Bip") === Bip
f("Bar") === Bar
f("...") === Exception (or maybe returns None)?
You could use macros, but it may be easier to just use simple Java reflection:
namespace org.example
import scala.util.control.Exception._
object Demo extends App {
sealed trait Foo
case class Bar() extends Foo
case class Bip() extends Foo
def makeFoo(s: String): Option[Foo] = {
catching(classOf[Exception]).opt(Class.forName("org.example.Demo$" + s).newInstance.asInstanceOf[Foo])
}
println(makeFoo("Bar")) // Some(Bar())
println(makeFoo("Bip")) // Some(Bip())
println(makeFoo("Bop")) // None
}
If you put all the case classes in a single object container like I did above, the class names should be pretty predictable.
Edit: Added optional wrapper for exceptional cases.
I'm using reflection to parse all public variable accessors from classes extending a trait called Component with the following call:
def iterate[T <: Component : TypeTag : ClassTag](component: T) {
...
ru.typeOf[T].members.filter(...)
...
}
However, this only works if the class type implementing the Component trait is visible during the call:
val myComp: MyComponent = new MyComponent()
iterate(myComp) // works
val myComp: Component = new MyComponent()
iterate(myComp) // Doesn't work, no members of MyComponent found in scope
One solution would be to define the implementing type in the trait (MyComponent extends Component[MyComponent]), but since I'm digging around with reflection anyway I was wondering if the variables of MyComponent are accessible from behind the trait.
I think you can get Type from java.lang.Class. See the example below.
╰─$ scala
Welcome to Scala version 2.11.2 (OpenJDK 64-Bit Server VM, Java 1.7.0_65).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :paste
// Entering paste mode (ctrl-D to finish)
import scala.reflect._
import scala.reflect.runtime.universe._
trait Component {
def parent: Int = 0
}
class MyComponent extends Component {
def child: Int = 0
}
def printRuntimeMemberNames(component: Component) = {
val cls = component.getClass
val mirror = runtimeMirror(cls.getClassLoader)
val symbol = mirror.staticClass(cls.getName)
val tpe = symbol.toType
val members = tpe.members
val memberNames = members.map(_.name.decodedName.toString)
println(memberNames.mkString(", "))
}
// Exiting paste mode, now interpreting.
import scala.reflect._
import scala.reflect.runtime.universe._
defined trait Component
defined class MyComponent
printRuntimeMemberNames: (component: Component)Unit
scala> val c: Component = new MyComponent
c: Component = MyComponent#3db7416a
scala> printRuntimeMemberNames(c)
<init>, child, parent, $init$, $asInstanceOf, $isInstanceOf, synchronized, ##, !=, ==, ne, eq, notifyAll, notify, clone, getClass, hashCode, toString, equals, wait, wait, wait, finalize, asInstanceOf, isInstanceOf
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
I have a class such as this:
class NormalClass[T <: NormalClass[T]] {
object One
object Two
}
and I wish to be able to create a new instance of the above class in a typed trait. The following def make in MetaClass creates an instance of T but it lacks the internal objects associated with NormalClass.
trait MetaClass[T <: NormalClass[T]] {
def make:T = this.getClass.getSuperclass.newInstance.asInstanceOf[T]
}
I have two questions, what is the reason for the missing objects and what is the best way, using reflection, to initiate a new class with internal objects from its type
EDIT: More Detail
The problem I am facing is if I then create an instance using make e.g. var f = make and I try to access and object method e.g. f.One.getSomething I get the error value One is not a member of type parameter T.
So I think your problem in particular is the reflection:
this.getClass.getSuperclass.newInstance.asInstanceOf[T]
Here, this is your instance of MetaClass, and there's no particular reason to believe that the superclass of this is the class you want to instantiate. For example:
class Foo extends NormalClass[Foo]
object Foo extends MetaClass[Foo]
In this case, the superclass of the object Foo is not a NormalClass at all, it's java.lang.Object. As a result, it won't have members like One or Two, and you'll get a ClassCastException if you try to cast it to T.
If you want the make method to instantiate an object of type T, then you need to get the runtime class of T, and then use that to create the new instance. You can accomplish this by implicitly acquiring a ClassTag:
class NormalClass[T <: NormalClass[T]] {
object One
object Two
}
trait MetaClass[T <: NormalClass[T]] {
def make(implicit classTag: scala.reflect.ClassTag[T]): T =
classTag.runtimeClass.newInstance.asInstanceOf[T]
}
// declare a class and an object for creating instances of that class
class Foo extends NormalClass[Foo]
object Foo extends MetaClass[Foo]
// create a new instance of Foo and access its fields
val foo = Foo.make
foo.One
foo.Two
I'm not sure what the issue is. This works for me:
scala> :paste
// Entering paste mode (ctrl-D to finish)
class NormalClass[T <: NormalClass[T]] {
object One
object Two
}
trait MetaClass[T <: NormalClass[T]] {
def make:T = this.getClass.getSuperclass.newInstance.asInstanceOf[T]
}
class X extends NormalClass[X]
// Exiting paste mode, now interpreting.
defined class NormalClass
defined trait MetaClass
defined class X
scala> new X with MetaClass[X]
res0: X with MetaClass[X] = $anon$1#404fe94c
scala> res0.One
res1: res0.One.type = NormalClass$One$#53d9f80
scala> res0.Two
res2: res0.Two.type = NormalClass$Two$#4d0948bd
If that doesn't answer your question, please clarify the issue you're having.