Why do val and def implement abstract methods at different times? - scala

I was working with scala and did something like this:
trait Foo { val a: String }
trait Foo2 extends Foo { val a = "foo" }
trait Bar extends Foo { val b = a + "-bar" }
object Bar2 extends Bar with Foo2
I expected that Bar2.b would be "foo-bar", but it ends up being "null-bar". Bar2.a is "foo" as expected.
If I change from val to def for definitions of 'a' like this:
trait Foo { def a: String }
trait Foo2 extends Foo { val a = "foo" }
trait Bar extends Foo { val b = a + "-bar" }
object Bar2 extends Bar with Foo2
Bar2.b is actually "foo-bar".
In example 2, the def 'a' from Foo2 that implements the abstract one in Foo is put into the definition of Bar2 before the val 'b' is evaluated. In example 1, the val 'a' from Foo2 overrides the val 'a' from Foo after val 'b' is defined in Bar/Bar2.
Why is this the case? Why do val and def implement abstract methods at different times?

You always want to use either def or lazy val in traits (rather than just val) to avoid the awkward behavior you discovered.
As for why, which gets to the low-level details of Scala's implementation in the JVM, check out Josh Suereth's excellent talk "Binary Resilience" from Scala Days 2012.

It's because there is Java behind. Initialized (non abstract) vals are translated to public getters with private fields and they are initialized in certain order. Abstract vals are just getters. Check Java documentation on this. You may also see early initializers feature of Scala to find a better solution:
In Scala, what is an "early initializer"?
And also order of mixing-in matters. This should give you the right result:
object Bar2 extends Foo2 with Bar

Related

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.

Built-in Support for String -> Trait?

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.

In what scenario does self-type annotation provide behavior not possible with extends

I've tried to come up with a composition scenario in which self-type and extends behave differently and so far have not found one. The basic example always talks about a self-type not requiring the class/trait not having to be a sub-type of the dependent type, but even in that scenario, the behavior between self-type and extends seems to be identical.
trait Fooable { def X: String }
trait Bar1 { self: Fooable =>
def Y = X + "-bar"
}
trait Bar2 extends Fooable {
def Y = X + "-bar"
}
trait Foo extends Fooable {
def X = "foo"
}
val b1 = new Bar1 with Foo
val b2 = new Bar2 with Foo
Is there a scenario where some form of composition or functionality of composed object is different when using one vs. the other?
Update 1: Thanks for the examples of things that are not possible without self-typing, I appreciate the information, but I am really looking for compositions where self and extends are possible, but are not interchangeable.
Update 2: I suppose the particular question I have is why the various Cake Pattern examples generally talk about having to use self-type instead of extends. I've yet to find a Cake Pattern scenario that doesn't work just as well with extends
Cyclic references can be done with self-types but not with extends:
// Legal
trait A { self: B => }
trait B { self: A => }
// Illegal
trait C extends D
trait D extends C
I use this sometimes to split up implementations across multiple files, when there are cyclic dependencies.
Also,
scala> trait A { def a: String ; def s = "A" }
defined trait A
scala> trait B { _: A => def s = "B" + a }
defined trait B
scala> trait C extends A { def a = "c" ; override def s = "C" }
defined trait C
scala> new C {}.s
res0: String = C
scala> new A with B { def a = "ab" }.s
<console>:10: error: <$anon: A with B> inherits conflicting members:
method s in trait A of type => String and
method s in trait B of type => String
(Note: this can be resolved by declaring an override in <$anon: A with B>.)
new A with B { def a = "ab" }.s
^
scala> new A with B { def a = "ab" ; override def s = super[B].s }.s
res2: String = Bab
The point, if there is one, is that B.s doesn't override A.s.
That's not as motivational as the other answer.
The generic parameter must be the type itself:
trait Gen[T] {self : T => ...}
I don't see how you can get this constraint in say java or C#. It may however be approximated with
trait Gen[T] {
def asT : T // abstract
}
Also,
as for self type, it needs a trait to mix in. It cannot use class or object. The weird thing is it allows to define a class can mix in with class, but it only fails compilation when you try to instantiate it. see this question:
why self-type class can declare class
The biggest difference is in the public interface that you end up with. Let's take the example you give (slightly simplified):
trait Fooable { def foo: String = "foo" }
trait Bar1 { self: Fooable =>
def Y = foo + "-bar"
}
trait Bar2 extends Fooable {
def Y = foo + "-bar"
}
// If we let type inference do its thing we would also have foo() in the public interface of b1, but we can choose to hide it
def b1:Bar1 = new Bar1 with Fooable
// b2 will always have the type members from Bar2 and Fooable
def b2:Bar2 = new Bar2{}
// Doesn't compile - 'foo' definition is only visible inside the definition of Bar1
println(b1.foo)
// Compiles - 'foo' definition is visible outside the definition of Bar2
println(b2.foo)
So if you want to use the capabilities of a trait without necessarily letting your clients know that you are mixing the trait in, then you should use the self-type annotation.
Self-type annotation does not expose the public interface of the underlying type.
Extending another type always exposes the public interface of the parent type.

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