This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Re: null option - initialization order

1 reply
Tony Morris 2
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
P'raps, but I just saw a wrong statement. Here it is again:
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.

Carry on.


On 08/24/2011 09:53 AM, Naftoli Gugenheim wrote:
ivLJmvLZOhw [at] mail [dot] gmail [dot] com" type="cite"> But you're overriding an abstract val, about which there was no doubt.

On Tue, Aug 23, 2011 at 7:46 PM, Tony Morris <tonymorris [at] gmail [dot] com" rel="nofollow">tonymorris [at] gmail [dot] com> wrote:
Sure. I just put all that aside to point out that there is at least one legitimate use-case for overriding a val. I chose that particular use-case because it is used specifically to *adhere* to the liskov substitution rule rather than break it. For example, to implement equals properly:

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:
I think Daniel's point was that if the superclass assigned one value to the val, then code that accepts an object with the superclass type would assume it has the value specified in the superclass. If then a subclass assigns a different value to it, that breaks the code's assumption. As opposed to where the superclass only defines an abstract val; then there's no assumption to break. I disagreed. As implied by the quote I posted, Liskov doesn't say that subclasses can't behave differently then the superclass; only that they must follow its contract. Not all code is a contract. Types certainly are, and I suppose anything documented explicitly as being a contract is; but actual implementation is not.

On Tue, Aug 23, 2011 at 7:26 PM, Tony Morris <tonymorris [at] gmail [dot] com" target="_blank" rel="nofollow">tonymorris [at] gmail [dot] com> wrote:
On 08/24/2011 09:25 AM, Naftoli Gugenheim wrote:
What?

On Tue, Aug 23, 2011 at 7:15 PM, Tony Morris <tonymorris [at] gmail [dot] com" target="_blank" rel="nofollow">tonymorris [at] gmail [dot] com> 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.

sealed trait StrictIdentity[A] { val value: A }; object StrictIdentity { implicit def ToStrictIdentity[A](a: A): StrictIdentity[A] = new StrictIdentity[A] { val value = a } }


-- 
Tony Morris
http://tmorris.net/



There are many legitimate use-cases for overriding a val. Suggest revision.

-- 
Tony Morris
http://tmorris.net/




-- 
Tony Morris
http://tmorris.net/




-- 
Tony Morris
http://tmorris.net/

Naftoli Gugenheim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: null option - initialization order
From this we can derive the importance of context! :)

On Tue, Aug 23, 2011 at 7:55 PM, Tony Morris <tonymorris [at] gmail [dot] com> wrote:
P'raps, but I just saw a wrong statement. Here it is again:
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.

Carry on.


On 08/24/2011 09:53 AM, Naftoli Gugenheim wrote:
But you're overriding an abstract val, about which there was no doubt.

On Tue, Aug 23, 2011 at 7:46 PM, Tony Morris <tonymorris [at] gmail [dot] com> wrote:
Sure. I just put all that aside to point out that there is at least one legitimate use-case for overriding a val. I chose that particular use-case because it is used specifically to *adhere* to the liskov substitution rule rather than break it. For example, to implement equals properly:

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:
I think Daniel's point was that if the superclass assigned one value to the val, then code that accepts an object with the superclass type would assume it has the value specified in the superclass. If then a subclass assigns a different value to it, that breaks the code's assumption. As opposed to where the superclass only defines an abstract val; then there's no assumption to break. I disagreed. As implied by the quote I posted, Liskov doesn't say that subclasses can't behave differently then the superclass; only that they must follow its contract. Not all code is a contract. Types certainly are, and I suppose anything documented explicitly as being a contract is; but actual implementation is not.

On Tue, Aug 23, 2011 at 7:26 PM, Tony Morris <tonymorris [at] gmail [dot] com> wrote:
On 08/24/2011 09:25 AM, Naftoli Gugenheim wrote:
What?

On Tue, Aug 23, 2011 at 7:15 PM, Tony Morris <tonymorris [at] gmail [dot] com> 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.

sealed trait StrictIdentity[A] { val value: A }; object StrictIdentity { implicit def ToStrictIdentity[A](a: A): StrictIdentity[A] = new StrictIdentity[A] { val value = a } }


-- 
Tony Morris
http://tmorris.net/



There are many legitimate use-cases for overriding a val. Suggest revision.

-- 
Tony Morris
http://tmorris.net/




-- 
Tony Morris
http://tmorris.net/




-- 
Tony Morris
http://tmorris.net/


Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland