Behavior of overridden attribute vs a method in scala - scala

Let us define simplest inheritance:
class A { val base: String = { println("a hello"); "hello" } }
class B extends A { override val base: String = { println("b hi"); "B hello"} }
Now let's try it out:
scala> new B().base
a hello
b hi
res0: String = B hello
So .. many (/most?) of you out there will likely not be surprised by this. I was . It had been my (incorrect ..) assumption that the B.base would completely override A.base . Instead we see both* methods being invoked : the base method A.base then the overriding method B.base.
Ok then .. so is it true that in order to avoid this doubling-up behavior that the val must be converted to a def (method) ?
class A { def base: String = { println("a hello"); "hello" } }
class B extends A { override def base: String = { println("b hi"); "B hello"} }
And now we have the desired behavior:
scala> new B().base
b hi
res1: String = B hello
Given this situation: when is overriding val useful within the body of a class?

It had been my (incorrect ..) assumption that the B.base would completely override A.base . Instead we see both methods being invoked : the base method A.base then the overriding method B.base.
No, we don't. The println calls in both A.base and B.base happen in the constructor, not when you access base. This is just what (non-lazy) member val means: the right-hand side is executed in the constructor and the result (just "hello" or "B hello" in your case) is stored into a field. Accessing base just returns the value of that field.
And superclass constructor is always fully executed before the subclass constructor, there's no way to override it (you can override any methods it invokes, but you need to be careful so they don't rely on subclass' state which isn't initialized yet).
scala> val b = new B()
a hello
b hi
scala> b.base
res0: String = B hello
when is overriding val useful within the body of a class?
When you want the subclass' val to have a different value, of course.

LAZY val
It came to me ..
class A { lazy val base: String = { println("a hello"); "hello" } }
class B extends A { override lazy val base: String = { println("b hi"); "B hello"} }
And now we get expected behavior:
scala> new B().base
b hi
res1: String = B hello

Related

Why would trait's val be evaluated if it is overridden in class?

scala> trait A { val a = { println("i'm invoked"); "1" } }
defined trait A
scala> class B extends A { override val a = { println("i'm invoked B"); "2" } }
defined class B
scala> (new B).a
i'm invoked
i'm invoked B
res0: String = 2
How can I avoid the val a in trait A being evaluated? I tried using lazy val and that works, but would be interested in knowing if there's an alternative way to do this. Thanks.
As described in this Scala doc:
Initialization of strict vals is done in the following order:
Superclasses are fully initialized before subclasses.
Otherwise, in declaration order.
The clause "fully initialized before" explains why a strict val is evaluated despite being overriden in the subclass.
Besides lazy val, an alternative is to replace val with def in your trait:
trait A { def a = { println("i'm invoked"); "1" } }
class B extends A { override def a = { println("i'm invoked B"); "2" } }
(new B).a
// i'm invoked B
// res1: String = 2

Implicit conversions in scala

Does Scala have implicit conversions for objects? For example, if I have a method with the following signature:
object Foo {
def print(message: String) = println(message)
}
class Bar {
val baz = 1
}
How can I call Foo.print(new Bar)?
Can I put a method on the Bar class to implicitly convert Bar instance to a string without having to call toString in the argument?
C# has this and I'm wondering if scala does too.
Let's say we have Scala enum:
object Color extends Enumeration {
type Method = Value
val RED, BLUE, GREEN = Value
}
Then I have a class:
object ColorPrinter {
def print(x: String) = {
println(x)
}
}
ColorPrinter's print method can't be changed.
I want to call into ColorPrinter.print(Color.RED), but I can't do that. I would have to call it like this: ColorPrinter.print(Color.RED.toString).
I want to avoid having to toString
Converting things implicitly to basic types, like String or Int isn't really a very good idea (the implicit conversion may trigger in places where you do not expect it to, creating subtle, hard to debug, issues).
Why not just make it explicit? ?
class Bar {
val baz = 1
def print = Foo.print(toString)
}
new Bar().print
You can put implicit conversions that can be applied automatically without importing into the companion object of the class:
class Bar {
val baz = 1
}
// This should be the companion object of `Bar`, so if in console, use :paste mode
object Bar {
implicit def toString(bar: Bar): String = bar.toString
}
scala> Foo.print(new Bar) // works without `import Bar._`
$line7.$read$$iw$$iw$Bar#280ecc33
For Enumerations you can put conversions into the object itself:
object Color extends Enumeration {
type Method = Value
val RED, BLUE, GREEN = Value
implicit def toString(value: Value): String = value.toString
}
scala> ColorPrinter.print(Color.RED) // works without `import Color._`
RED
You can read more about implicit resolution in Scala in this answer: https://stackoverflow.com/a/5598107/1098230
Here is a typical approach,
yes, Implicit's very similar to C# static methods and its implemented in adhoc way:
object Foo {
def print(message: String) = println(message)
}
class Bar {
val baz = 1
}
object BarToStringMaker {
implicit def barToString(b : Bar) : String = b.baz.toString
}
import BarToStringMaker._
Foo.print(new Bar)
more reading:
http://www.artima.com/pins1ed/implicit-conversions-and-parameters.html
hope that helps,

Trouble with overriding a variable in abstract class

I'm new to scala and have the following question about overriding a variable in an abstract class.
abstract class ExampleClass1 {
val testVar = (i: String) => {
i + " A"
}
def exampleMethod1() = {
print testVar
}
}
object ExampleObject1 extends ExampleClass1 {
def getExampleValue() = {
exampleMethod1()
}
}
ExampleClass1 and ExampleObject1 are in one module. My module is calling ExampleObject1.getExampleValue. I want to change the behavior of testVar in ExampleClass1. Is it possible to do this without changing ExampleObjectt1?
Thank you
If you want to change a value after the class is instantiated, then you should use var instead of val, but without any further information it seems that there is a flaw in your design.
If you want to set the value of the given string on object creation, you can use something like this:
scala> abstract class ExampleClass1(val i: String)
defined class ExampleClass1
scala> object ExampleObject1 extends ExampleClass1("A")
defined object ExampleObject1
scala> ExampleObject1.i
res1: String = A
Or if you want to use given string as a parameter:
scala> abstract class ExampleClass2 {
| def test(i: String) = i + " A"
| }
defined class ExampleClass2
scala> object ExampleObject2 extends ExampleClass2
defined object ExampleObject2
scala> ExampleObject2.test("B")
res2: String = B A
What is your goal?

When to use val or def in Scala traits?

I was going through the effective scala slides and it mentions on slide 10 to never use val in a trait for abstract members and use def instead. The slide does not mention in detail why using abstract val in a trait is an anti-pattern. I would appreciate it if someone can explain best practice around using val vs def in a trait for abstract methods
A def can be implemented by either of a def, a val, a lazy val or an object. So it's the most abstract form of defining a member. Since traits are usually abstract interfaces, saying you want a val is saying how the implementation should do. If you ask for a val, an implementing class cannot use a def.
A val is needed only if you need a stable identifier, e.g. for a path-dependent type. That's something you usually don't need.
Compare:
trait Foo { def bar: Int }
object F1 extends Foo { def bar = util.Random.nextInt(33) } // ok
class F2(val bar: Int) extends Foo // ok
object F3 extends Foo {
lazy val bar = { // ok
Thread.sleep(5000) // really heavy number crunching
42
}
}
If you had
trait Foo { val bar: Int }
you wouldn't be able to define F1 or F3.
Ok, and to confuse you and answer #om-nom-nom—using abstract vals can cause initialisation problems:
trait Foo {
val bar: Int
val schoko = bar + bar
}
object Fail extends Foo {
val bar = 33
}
Fail.schoko // zero!!
This is an ugly problem which in my personal opinion should go away in future Scala versions by fixing it in the compiler, but yes, currently this is also a reason why one should not use abstract vals.
Edit (Jan 2016): You are allowed to override an abstract val declaration with a lazy val implementation, so that would also prevent the initialisation failure.
I prefer not use val in traits because the val declaration has unclear and non-intuitive order of initialization. You may add a trait to already working hierarchy and it would break all things that worked before, see my topic: why using plain val in non-final classes
You should keep all things about using this val declarations in mind which eventually road you to an error.
Update with more complicated example
But there are times when you could not avoid using val. As #0__ had mentioned sometimes you need a stable identifier and def is not one.
I would provide an example to show what he was talking about:
trait Holder {
type Inner
val init : Inner
}
class Access(val holder : Holder) {
val access : holder.Inner =
holder.init
}
trait Access2 {
def holder : Holder
def access : holder.Inner =
holder.init
}
This code produces the error:
StableIdentifier.scala:14: error: stable identifier required, but Access2.this.holder found.
def access : holder.Inner =
If you take a minute to think you would understand that compiler has a reason to complain. In the Access2.access case it could not derive return type by any means. def holder means that it could be implemented in broad way. It could return different holders for each call and that holders would incorporate different Inner types. But Java virtual machine expects the same type to be returned.
I agree with the other answers about avoiding abstract vals for the reason that it provides more options to implementations.
There are cases where you might need them:
For a path-dependent type (as mentioned by #0__).
Where implementations might be expensive and it is used in a concrete def.
(Are there others? If so please comment and I'll add them in).
The more important things to know is when it is safe to override something with a val and to have a lazy val that does not override something.
Rule 1: Never override a val or def with a non-lazy val unless it is a constructor parameter:
trait TraitWithVal {
// It makes no difference if this is concrete or abstract.
val a: String
val b: String = a
}
class OverrideValWithVal extends TraitWithVal {
// Bad: b will be null.
override val a: String = "a"
}
class OverrideValWithLazyVal extends TraitWithVal {
// Ok: b will be "a".
override lazy val a: String = "a"
}
// Ok: b will be "a".
class OverrideValWithConstructorVal(override val a: String = "a") extends TraitWithVal
//class OverrideValWithDef extends TraitWithVal {
// // Compilation error: method a needs to be a stable, immutable value.
// override def a: String = "a"
//}
println((new OverrideValWithVal).b) // null
println((new OverrideValWithLazyVal).b) // a
println((new OverrideValWithConstructorVal).b) // a
The same rule applies to a def:
trait TraitWithDef {
// It makes no difference if this is concrete or abstract.
def a: String
val b: String = a
}
class OverrideDefWithVal extends TraitWithDef {
// Bad: b will be null.
override val a: String = "a"
}
class OverrideDefWithLazyVal extends TraitWithDef {
// Ok: b will be "a".
override lazy val a: String = "a"
}
// Ok: b will be "a".
class OverrideDefWithConstructorVal(override val a: String = "a") extends TraitWithDef
class OverrideDefWithDef extends TraitWithDef {
// Ok: b will be "a".
override def a: String = "a"
}
println((new OverrideDefWithVal).b) // null
println((new OverrideDefWithLazyVal).b) // a
println((new OverrideDefWithConstructorVal).b) // a
println((new OverrideDefWithDef).b) // a
You might be wondering whether it would be ok to override a val with another val so long as it isn't used during initialisation. There is at least one edge cases which break this:
trait TraitWithValAndLazyVal {
val a: String = "A"
def b: String = a
}
class OverrideLazyValWithVal extends TraitWithValAndLazyVal {
// Bad: This on its own is ok but not if it is indirectly referenced during initialisation and overridden.
override val a = "a"
val c = b
}
class OverrideValWithVal extends OverrideLazyValWithVal {
override val a = "a"
}
println((new OverrideValWithVal).a) // a
println((new OverrideValWithVal).b) // a
println((new OverrideValWithVal).c) // null
Given that we already apply this rule to overriding defs then this makes using vals a little more acceptable in my opinion.
If you use a linter to enforce the override keyword and make sure your code never has any override val definitions then you are good.
You might be able to allow final override val but it's possible there are other edge cases that I haven't thought of.
Rule 2: Never use a lazy val that is not overriding another lazy val or def.
As far as I can tell there also is no good reason to have a lazy val that isn't overriding something. All the examples that I can come up with where it is needed, it is needed only because it violates Rule 1 and exposes the edge case I described earlier.
For example:
trait NormalLookingTrait {
def a: String
val b: String = a
}
trait TraitWithAbstractVal extends NormalLookingTrait {
val c: String
}
class OverrideValWithVal extends TraitWithAbstractVal {
override def a: String = c
override val c = "a"
}
println((new OverrideValWithVal).a) // a
println((new OverrideValWithVal).b) // null
println((new OverrideValWithVal).c) // a
So we make b a lazy val:
trait SuspiciousLookingTrait2 {
def a: String
lazy val b: String = a
}
trait TraitWithAbstractVal2 extends SuspiciousLookingTrait2 {
val c: String
}
class OverrideValWithVal2 extends TraitWithAbstractVal2 {
override def a: String = c
override val c = "a"
}
println((new OverrideValWithVal2).a) // a
println((new OverrideValWithVal2).b) // a
println((new OverrideValWithVal2).c) // a
Looks ok, except when we go one step further:
trait SuspiciousLookingTrait2 {
def a: String
lazy val b: String = a
}
trait TraitWithAbstractVal2 extends SuspiciousLookingTrait2 {
val c: String
}
class OverrideValWithVal2 extends TraitWithAbstractVal2 {
override def a: String = c
override val c = "a"
val d = b
}
class OverrideValWithVal3 extends OverrideValWithVal2 {
override val c = "a"
}
println((new OverrideValWithVal3).a) // a
println((new OverrideValWithVal3).b) // null
println((new OverrideValWithVal3).c) // a
println((new OverrideValWithVal3).d) // null
I now get what people mean when they say to only use lazy when it is absolutely necessary and never for delayed initialisation.
It's probably safe to break this rule if the trait / class is final but even that smells fishy.
Always using def seems a bit awkward since something like this won't work:
trait Entity { def id:Int}
object Table {
def create(e:Entity) = {e.id = 1 }
}
You will get the following error:
error: value id_= is not a member of Entity

What is the difference between the different overriding methods in Scala?

Scala lets you override a method in two legal ways:
Given super class:
class A {
def a = "A"
}
We can override the method "a" by:
class B extends A {
override def a = "B"
}
and
class B extends A {
override def a() = "B"
}
both seem to override the method "a" correctly. What is the design decision behind this? Why allow for "a()" in B to override "a" in A?
This hasn't always been the case (from the change log of the language specification):
Scala version 2.0 also relaxes the rules of overriding with respect to
empty parameter lists. The revised definition of matching members
(§5.1.3) makes it now possible to override a method with an explicit,
but empty parameter list () with a parameterless method, and vice
versa.
You are correct that this seems like an odd design decision, given that there are observable differences between parameterless methods and ones with empty parameter lists. For example, suppose you have the following:
class A { def a = "A" }
class B extends A { override def a = "B" }
class C extends A { override def a() = "C" }
Now we can write the following, as expected:
scala> (new B).a
res0: java.lang.String = B
scala> (new C).a
res1: java.lang.String = C
And this:
scala> (new C).a()
res2: java.lang.String = C
But not this:
scala> (new B).a()
<console>:10: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
Unspecified value parameter index.
(new B).a()
So Scala does make a distinction between the two, which obviously must be reflected in the bytecode. Suppose we compile the following:
class A { def a = "A" }
class B extends A { override def a = "B" }
And then run:
javap -verbose B > noArgList.txt
Then change the code to this:
class A { def a = "A" }
class B extends A { override def a() = "B" }
Recompile, and run:
javap -verbose B > emptyArgList.txt
And finally check for differences:
< MD5 checksum 88aeebf57b645fce2b2fcd2f81acdbbd
---
> MD5 checksum 3733b3e4181b4b2f4993503d4c05770e
32c32
< #18 = Utf8 }1A!
\t\t!ICaT-9uszaE\r)\"a\tI!!\"1Q!Dg
jiz\"a\tAQ!BY\t!Y G.Y11bU2bY|%M[3di\")C%1A(
/A$H3)!dGYtwMCQM^1\nyI\"AB*ue&tw\r
---
> #18 = Utf8 }1A!
\t\t!ICaT-9uszaE\r)\"a\tI!!\"1Q!Dg
jiz\"a\tAQ!BY\t! G.Y11bU2bY|%M[3di\")C%1A(
/A$H3)!dGYtwMCQM^1\nyI\"AB*ue&tw\r
So there is a difference—the two versions have different values for the ScalaSignature annotation.
As to why the change was made in Scala 2.0: the specification notes that it allows this:
class C {
override def toString: String = ...
}
My guess is that the language designers just didn't see a reason to require users to remember which approach the overridden methods used in cases like this.