- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
null option - initialization order
For example:
scala> class A { val x = Some(1); println (x) }
defined class A
scala> class B extends A { override val x = Some(2); println(x) }
defined class B
scala> new B
null
Some(2)
res1: B = B@48b89bc5
scala>
I understand Paul’s explanation here https://github.com/paulp/scala-faq/wiki/Initialization-Order - initializing fields only once - but this kind of side-effect from a client derived class onto a base library class is bad… it gives birth to monsters like this null Option…
Yes, this is also possible, but it’s not an excuse:
scala> val x : Option[Int] = null
x: Option[Int] = null
is there nothing we can do to make this behavior more intuitive? Just a not in the style guide?
thanks,
Razie










Re: null option - initialization order
You should really *not* override a val. If it is a val, then you are
kind of guaranteeing the return value is that one. To change it in a
subclass is a violation of the liskov principle.
The simplest way to achieve the same thing is this:
class A { def x = Some(1); println(x) }
class B extends A { override def x = Some(2); println(x) }
You can even override A's def x with a val x.
This will only cause trouble with frameworks that search for fields
through reflection. In that case, you'd better just go with a var
instead, and possibly make it protected and add a public getter if
needed.
On Tue, Aug 23, 2011 at 13:21, Razvan Cojocaru wrote:
> For example:
>
>
>
> scala> class A { val x = Some(1); println (x) }
>
> defined class A
>
>
>
> scala> class B extends A { override val x = Some(2); println(x) }
>
> defined class B
>
>
>
> scala> new B
>
> null
>
> Some(2)
>
> res1: B = B@48b89bc5
>
>
>
> scala>
>
>
>
>
>
> I understand Paul’s explanation here
> https://github.com/paulp/scala-faq/wiki/Initialization-Order -
> initializing fields only once - but this kind of side-effect from a client
> derived class onto a base library class is bad… it gives birth to monsters
> like this null Option…
>
>
>
> Yes, this is also possible, but it’s not an excuse:
>
>
>
> scala> val x : Option[Int] = null
>
> x: Option[Int] = null
>
>
>
> is there nothing we can do to make this behavior more intuitive? Just a not
> in the style guide?
>
>
>
> thanks,
>
> Razie
>
>
>
>
>
>
>
>
Re: null option - initialization order
sealed trait StrictIdentity[A] { val value: A }; object StrictIdentity { implicit def ToStrictIdentity[A](a: A): StrictIdentity[A] = new StrictIdentity[A] { val value = a } }
Re: null option - initialization order
On Tue, Aug 23, 2011 at 20:15, Tony Morris wrote:
> On 08/24/2011 02:40 AM, Daniel Sobral wrote:
>
> You should really *not* override a val. If it is a val, then you are
> kind of guaranteeing the return value is that one. To change it in a
> subclass is a violation of the liskov principle.
>
> Bzzt.
No Bzzt.
> sealed trait StrictIdentity[A] { val value: A }; object StrictIdentity {
> implicit def ToStrictIdentity[A](a: A): StrictIdentity[A] = new
> StrictIdentity[A] { val value = a } }
You should have declared the abstract "value" to be a def, though you
might well want to provide the guarantees of a "val" here.
BUT, in this case you are overriding an abstract member, which is a
very different thing than what was being done.
Re: null option - initialization order
I think the issue for the original poster was that the current behavior is unintuitive, not whether or not it is good design to override a val.
Perhaps the compiler could warn about overridden vals?
Best,Kjetil
Re: null option - initialization order
On Tue, Aug 23, 2011 at 7:15 PM, Tony Morris <tonymorris [at] gmail [dot] com> wrote:
Re: null option - initialization order
There are many legitimate use-cases for overriding a val. Suggest revision.
Re: null option - initialization order
On Tue, Aug 23, 2011 at 7:26 PM, Tony Morris <tonymorris [at] gmail [dot] com> wrote:
Re: null option - initialization order
trait TypeSafeEquals[A] { def equal: A => A => Boolean }
sealed trait StrictIdentity[A] { val value: A; def ===(a: A)(implicit e: TypeSafeEqual[A]) = e.equal(value)(a) }; object StrictIdentity { implicit def ToStrictIdentity[A](a: A): StrictIdentity[A] = new StrictIdentity[A] { val value = a } }
On 08/24/2011 09:38 AM, Naftoli Gugenheim wrote:
Re: null option - initialization order
On Tue, Aug 23, 2011 at 7:46 PM, Tony Morris <tonymorris [at] gmail [dot] com> wrote:
Re: null option - initialization order
On Tue, Aug 23, 2011 at 12:40 PM, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:
Is overriding a method and changing its behavior a violation?
Re: null option - initialization order
On Tue, Aug 23, 2011 at 19:43, Naftoli Gugenheim wrote:
>
>
> On Tue, Aug 23, 2011 at 12:40 PM, Daniel Sobral wrote:
>>
>> You should really *not* override a val. If it is a val, then you are
>> kind of guaranteeing the return value is that one. To change it in a
>> subclass is a violation of the liskov principle.
>
> Is overriding a method and changing its behavior a violation?
Sure, in this sense:
class A {
def lightState = // true if on
}
class B extends A {
override def lightState = // false if on
}
That changed the behavior. But note that a *val* gives more guarantees
than a *def*. In particular, you are guaranteed that two calls to a
val will always return the same value for an instance.