Override field with parameterless method - scala

I am currently learning Scala and I am reading (from cover to cover) Martin Ordesky's book. In chapter 10 I found this:
Great I both understand and like this. So I tried an example:
class Father {
def x = 1 // Method
}
class Child extends Father {
override val x = 1; // Field
}
However, if you try to override an attribute with a method:
class Father {
val x = 1; // Field
}
class Child extends Father {
override def x = 1 // Method
}
I get a compiler error:
method x needs to be a stable, immutable value
override def x = 1
It doesn't work neither if x in Father is var:
method x cannot override a mutable variable
override def x = 1
So we have two cases (and my two questions):
Trying to override an inmutable field: Is this forbidden in order to guarantee x won't be overriden by a method whose value changes over time? Is there any other reason?
Trying to override a mutable field: Why can't a mutable field be overriden? I initially thought that it is to avoid class users assigning values to parameterless methods but then no parameterless method should be allowed.

Allowing overriding of a val by a def would require going through lots of hoops in the generated constructor, and there would be redundant fields in subclasses. It's technically possible to implement this but there are no benefits.
Allowing overriding of a var by a def wouldn't make sense. What would assigning to it mean?

Related

How to override abstract trait type in subclasses [duplicate]

This question already has answers here:
Is it possible to override a type field?
(1 answer)
Why is this invalid Scala?
(1 answer)
Closed 2 years ago.
I would like to define a trait with a method that returns a generic type value and
then define a class hierarchy where a parent class defines a specific generic type value and the subclass defines a different one, like so:
trait Thingy {
type T
def doIt(): T
}
class A extends Thingy {
override type T = Array[Int]
override def doIt(): T = {
Array[Int](1, 2, 3)
}
}
class B extends A {
override type T = Array[String]
def doIt(): T = {
Array[String]("stringy")
}
}
val aa = new A()
println(aa.doIt().length)
val bb = new B()
println(bb.doIt()(0))
This generates compile errors
ScalaFiddle.scala:16: error: overriding type T in class A, which equals scala.this.Array[scala.this.Int];
type T has incompatible type;
found : B.this.T
(which expands to) scala.this.Array[String]
required: A.this.T
(which expands to) scala.this.Array[scala.this.Int]
override type T = Array[String]
^
ScalaFiddle.scala:17: error: overriding method doIt in class A of type ()B.this.T;
method doIt needs `override' modifier;
found : ()B.this.T
(which expands to) ()scala.this.Array[String]
required: ()A.this.T
(which expands to) ()scala.this.Array[scala.this.Int]
def doIt(): T = {
^
I have tried parameterized types, abstract classes, and traits but I can't seem to get it right.
Can someone explain if there is a way to do it?
Adding use case to answer Luis Miguel Mejía Suárez
I'm simply trying to use inheritance to inherit common methods while maintaining 2 different data structures to represent the internal state of each class.
Say the parent class is a Grid that represents its internal data structure with a 2D Array of Cells of known dimensions
class Grid(var rows, var columns) {
protected var _grid: Array[Array[Cell]] = makeGrid()
def makeGrid(): Array[Array[Cell]] = {
var g = Array.ofDim[Cell](rows, columns)
// populate g
g
}
}
and I have a subclass that needs to represent the grid with a mutable ArrayBuffer:
class OtherGrid(var rows) extends Grid(rows, 1) {
protected var _grid: ArrayBuffer[ArrayBuffer[Cell]] = makeGrid()
override def makeGrid(): ArrayBuffer[ArrayBuffer[Cell]] = {
// initialize and populate the grid
}
}
Is this the wrong way to go about things in a functional programming language?

Is this class Immutable or mutable

Is the below Scala class is mutable or immutable?
I believe that its immutable as I can't edit the variables or access them once its created but whats making me doubt myself is the fact that it returns the current instance of a variable using its functions. It also does not have final in front of it which is further making me doubt myself.
class person(name:String, dob:String){
def getName = name
def getDob = dob
def display() = {
println("Name "+name+" dob: "+dob)
}
}
Thanks,
You have a misconception with the term Immutable:
I believe that its immutable as I can't edit the variables or access
them once its created
That's the definition of a private thing (method, variable, ...). Immutability refers to the fact that you cannot mutate state, that is, you can't change the value of something unless you create a new instance of it.
Let's see it with an example:
trait Foo{
def myMutableValue: Int
}
class Clazz extends Foo{
var myMutableValue = 1
def changeState(): Int = {
myMutableValue += 1
myMutableValue
}
}
val bar = new Clazz
bar.changeState() // myMutableValue = 2
bar.changeState() // myMutableValue = 3
bar.changeState() // myMutableValue = 4
bar.myMutableValue // myMutableValue = 4
With that example, in your instance of Clazz (bar) you're changing the state of a class attribute, in this case myMutableValue is changing its value every time I invoke changeState.
Please note that the class is public by default and changeState is also public and that doesn't means that is immutable.
Now, let's see an immutable approach:
trait Foo{
def myMutableValue: Int
}
class Clazz extends Foo{
val myMutableValue = 1
def changeState(): Int = myMutableValue + 1
}
val instance = new Clazz
instance.changeState() // myMutableValue = 2
instance.changeState() // myMutableValue = 2
instance.changeState() // myMutableValue = 2
instance.myMutableValue // 1
With this approach, every call to changeState will evaluate to 2, no matter how many times I call the function. That is, because we're dealing with an immutable value (val myMutableValue = 1). Every invocation of changeState will perform the evaluation and return a copy of that value. You're not modifying in any way the value of myMutableValue.
Please take a look to this and this.
Also, please take a look at your code, you have some errors:
By convention, class name should be capitalized (Person instead of person).
You don't need to reassign your class values with def (def getNameand def getDob). You can use class values as is.
Lastly:
It also does not have final in front of it which is further making me
doubt myself.
Again, you're talking about different things. final, as in Java, is a modifier to prevent your class to be extended. It doesn't relate in any way to immutability In adition, if you want to prevent mutability in your subclass you have to make all their members final (see this).
Since your example is coded in Scala you have all the tools that the language itself offers at your disposal (e.g. val, sealed, final)
Please note that I've used a trait to explain the possible use of def.
EDIT: about final modifier and immutability
Thanks to #Silvio Mayolo and #puhlen for the comments and clarification about final

proper use of scala traits and types

New to scala and trying to get the hang of the class system. Here's a simple set up:
sealed trait Shape{
def sides:Int
}
final case class Square() extends Shape {
def sides() = 4
}
final case class Triangle() extends Shape {
def sides() = 3
}
Now, I want to create a function that takes anything of type shape, which we know will have a sides() method implemented, and make use of that method.
def someFunction(a: Shape)={
val aShape = a()
aShape.sides()
}
But this hits an error at val aShape = a(), as there's no type a.
I realize that in this example, it's excessive to create someFunction, since sides() can be accessed directly from the objects. But my primary question is in the context of someFunction - I'd like to pass a class to a function, and instantiate an object of that class and then do something with that object. Thanks for your help.
What are you trying to do with that line of code? You already have a shape, the one passed in called a. Just remove that line and call a.sides().
Stylistically, there are several problems. First of all, class names should start with a capital letter. Second, sides seems like an immutable property, not a mutating method, so it should be declared and overridden with no parentheses. You also need override modifiers in your subclass. Last, you can do without the empty braces: {4} should just be 4.
There is several methods to do this. One is a complex one using reflection, second is little bit simplier, using a builder and third is most straightforward for your use case.
Just change definition of someFunction to
def someFunction(a: ()=>Shape)={
val aShape = a()
aShape.sides
}
so someFunction(Square) return 4 and someFunction(Triangle) returns 3 . Note this work only with case classes because real thing, we are passing here is not class itself, but it's auto-generated companion object
But more often there no need to define classes, you could write inside any context except top level thing just like
def square() = new Shape{
def sides() = 4
}
def triangle() = new Shape{
def sides() = 3
}
Next thing: methods with empty parameter list are generally reading as method that have side effects. So it is more convenient to define your type like
sealed trait Shape{
def sides:Int
}
and if you define your builders like
def square = new Shape{
def sides = 4
}
def triangle = new Shape{
def sides = 3
}
you should use them as someFunction(square _) telling, that you gonna use method call and not the value it's returning
And last thing is: if you really need the code, that creates some object, but it could contain complex computations, resource handling or some probable exception, so you want to hold over it's execution until it' really needed, you could use call-by-name parameters which is equivalent to R , which i assume you are familiar with
Unless shape has an apply function, you cannot call () on a shape object.
If you want to assign aShape to a, simply write val aShape = a.
But since I do not see the added value, you might as well call the sides function directly on a:
def someFunction(a:shape) = {
val sides = a.sides
// use sides
}
This is the closest translation for what you wrote:
sealed trait Shape {
def sides: Int
}
case object Square extends Shape {
override val sides = 4
}
case object Triangle extends Shape {
override val sides = 3
}
def someFunction(a: Shape) =
val shapeSides = a.sides
Some notes:
Classes in scala should be CamelCase
Your subclasses have no instance members, so you can use a singleton object
You if you have a: Shape it means that a is a Shape, and you haven't defined anything that would let you call () on it.
You can omit braces when there's only one expression inside
You can override a def with val if it's static

Scala 2.8: how to initialize child class

Consider the following code:
abstract class X {
def a:Unit
a
}
class Y extends X {
var s:String = "Hello"
def a:Unit = println ("String is "+s)
}
This gives the following output:
scala> new Y
String is null
res6: Y = Y#18aeabe
How can I get the parent class X to wait for s to be initialized when calling a
The parent's fields and the parent constructor are always initialized and run before the children's field and constructor. It means that the call to a happens before your var s is set in the child class.
In general, it's a bad idea to call a virtual method from a constructor; C++ even disallows it (or, rather than disallowing it, doesn't call the method implemented in the child class when called from the superclass's constructor).
However, you can fix it if you turn your var s in class Y into a lazy val or a def instead. lazy vals are initialized the first time their value is accessed, no matter by whom; defs pose no initialization issues like vars or vals. However, be careful not to call any other uninitialized structure from within the implementation of a, as the same problem will show up again.
Edit:
You can also use Scala's “early definitions” (or early initialization) feature:
class Y extends {
var s = "Hello"
} with X {
def a: Unit = println ("String is "+s)
}

Is it possible to inherit auxiliary constructors in Scala?

I wonder if it is possible to inherit auxiliary constructors in Scala?
I tested this code, and it complained
temp.scala:18: error: too many arguments for constructor Child: ()this.Child
val a = new Child(42)
^
abstract class Father {
var value: Int = 0
protected def setValue(v: Int) = {
value = v
}
protected def this(v: Int) = {
this()
setValue(v)
}
}
class Child extends Father {
}
val a = new Child(42)
But if i put
protected def this(v: Int) = {
this()
setValue(v)
}
in the Child class, everything is all right.
Absolutely not, and your example demonstrates why. You've introduced a mutable variable value that may or may not be initialised - depending on the exact constructor used.
This is a potential source for a great many problems, and so Scala made the decision that all object creation should ultimately be directed via the primary constructor, this ensuring consistent initialisation.
If you want value to have a default value, then you can specify it as a default parameter (in 2.8+):
abstract class Father(val value : Int = 0)
or you can use the auxiluary constructor to achieve the same effect in Scala 2.7:
abstract class Father(val value : Int) {
def this() = this(0)
}
With Father defined in either of the above ways, the following definitions of child are both valid:
class Child(v:Int) extends Father(v)
class Child extends Father()
You can also make value a var if you absolutely have to, but I strongly advise against it.
If the semantics of value mean that it's valid to not be initialised, then the correct Scala idiom is to declare it as Option[Int]:
abstract class Father(val value : Option[Int] = Some(0))
Your Child constructor have no parameter and you are trying to instanciate it with one ! You have to declare a parameter in your Child constructor and then pass it to the Father class, for example:
class Child(v:Int) extends Father(v) {
}
val a = new Child(42)