Quantcast

Why we can't override var in scala but can override val

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Why we can't override var in scala but can override val

priyank jain
Hi Guys, i am new to Scala and while going through Scala concepts got stumbled over the fact that val can be overridden in Scala but not vars. I am not able to find any convincing answer to this problem. Can someone help me on this

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Why we can't override var in scala but can override val

Bardur Arantsson
On 2017-02-17 06:36, priyank jain wrote:
> Hi Guys, i am new to Scala and while going through Scala concepts got
> stumbled over the fact that val can be overridden in Scala but not vars.
> I am not able to find any convincing answer to this problem. Can someone
> help me on this
>

I believe it's a soundness issue with variance. If you had e.g.

   class A() { ... }
   class B() extends A() { ... }

   trait Foo {
     var x: A
   }

   trait Bar extends Foo {
     override var x: B
   }

and someone had access to a reference to a Foo, then they might do

   foo.x = new A()

which would lead anyone accessing through a Bar reference to try to
access an A as a B... which is obviously not sound.

Regards,

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Why we can't override var in scala but can override val

Rex Kerr-2
This is correct.  The problem is that there isn't anything to override the var *with* that is safe.

Let's suppose we have a superclass `A`, a class `B`, and a subclass `C`.

If you look at the two halves of what a var can do:
  def x: B
  def x_=(b: B): Unit
you can see that the first part works with a subclass; if `C` is a subclass of `B`, then `override def x: C` will certainly be compatible with the superclass `def x: B` because the`C` is a `B`.  And that half is all of what a `val` can do, so it's fine to override a `val`.

If you look at the second half, you need to at least be able to store a `B`.  Storing only a `C` isn't going to cut it, but if you can store an `A` that is a *superclass* of `B`, that is cool too.  So `override def x_=(a: A): Unit` is also fine.  (We don't have a name for this alone.)

If you need to be both, which a var is, well, you can't be a superclass and you can't be a subclass, so you can only be the original class.

And you already are the original class so there's nothing to override at least at the type level.

"But wait!" you say.  "You can override the initial value safely with something else of the same type!"  That's potentially true (assuming you avoid depending on the value in the initializer), and Scala doesn't let you do this directly.

But you can do it, as long as you know you will want to in advance and build in the appropriate machinery:

case class N(value: Int) {}
class Foo { protected def initialN = N(0); var n: N = initialN }
class Bar extends Foo { override protected def initialN = N(1) }

I suppose it wouldn't hurt to allow `override var` to work like this, but right now it doesn't.

  --Rex


On Fri, Feb 17, 2017 at 7:10 AM, Bardur Arantsson <[hidden email]> wrote:
On 2017-02-17 06:36, priyank jain wrote:
> Hi Guys, i am new to Scala and while going through Scala concepts got
> stumbled over the fact that val can be overridden in Scala but not vars.
> I am not able to find any convincing answer to this problem. Can someone
> help me on this
>

I believe it's a soundness issue with variance. If you had e.g.

   class A() { ... }
   class B() extends A() { ... }

   trait Foo {
     var x: A
   }

   trait Bar extends Foo {
     override var x: B
   }

and someone had access to a reference to a Foo, then they might do

   foo.x = new A()

which would lead anyone accessing through a Bar reference to try to
access an A as a B... which is obviously not sound.

Regards,

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Why we can't override var in scala but can override val

Bardur Arantsson
On 2017-02-18 00:13, Rex Kerr wrote:
> This is correct.  The problem is that there isn't anything to override
> the var *with* that is safe.
>
> Let's suppose we have a superclass `A`, a class `B`, and a subclass `C`.
>
[--snip--]

Good point. If invariance were enforced, there'd be no problem. (Still,
it's a pretty niche thing, so it's understandable that it was left out.)

Regards,


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Loading...