Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: Extend concrete class with constructor parameters

I have this concrete class:

class Person (var name: String, var surname: String)

and I want to create another class that extends Person:

class Son (name: String, surname: String) extends Person(name, surname)

OK. But I do want the fields in the constructor of Son must be var and not val. How do I fix this? The fields must remain constructor parameters.

UPDATE #2

My problem is as follows: If I define a method in Son, this does not work if I change the value to the parameters of an instance of Son.

class Son (name: String, surname: String) extends Person(name, surname){
  def printSon = {
  if(this.name=="name")println("Error name Person")
  if(this.surname=="surname")println("Error surname Person")
  }
}

object main {
  def main(args: Array[String]): Unit = {}

  val Marco = new Son("Marco","Bianchi")
  Marco.printSon // So far everything is ok
  Marco.name="name"
  Marco.printSon // Here in control is not done, because Marco.name="name" writes in Person
  println("FINE")
}

name e surname in Son are of type val.

like image 430
user1826663 Avatar asked Nov 30 '12 14:11

user1826663


People also ask

How do I extend a class in Scala?

To extend a class in Scala we use extends keyword. there are two restrictions to extend a class in Scala : To override method in scala override keyword is required. Only the primary constructor can pass parameters to the base constructor.

Does an extended class need a constructor?

A class that extends another class does not inherit its constructors. However, the subclass must call a constructor in the superclass inside of its the subclass constructors!

Can an object extend a class Scala?

Objects and classes are not completely decoupled. An object can extend another class, making its fields and methods available in a global instance.

Can you extend multiple classes in Scala?

You can't extend multiple classes, but you can extend several traits. Unlike Java interfaces, traits can also include implementation (method definitions, data members, etc.). There is still a difference in that you can't instantiate a trait directly (similar to abstract classes in a way).


1 Answers

If I understand correctly you want the name and surname fields in Son to be immutable, as opposed to those in Person, which are vars.

That simply isn't possible. The only way to do it would be by overwriting:

class Person (var name: String, var surname: String)

//this won't compile
class Son(override val name: String, override val surname: String) extends Person(name, surname)

In Scala you cannot overwrite a var with a val - and it is pretty obvious why - subclasses can only override or add functionality to a superclass. If we wore to allow vals to override vars we would remove from the parent class the setter for the overridden field. This breaks the "is-a" relationship implied by inheritance.

What you could do is implement this like so:

trait Person {
    def name: String
    def surname: String
}

//this is fine now
class Son(val name: String, val surname: String) extends Person

//in case you want a type of person which can be changed.
class MutablePerson(var name: String, var surname: String) extends Person

Person now is a trait - it just provides a way of getting the name or surname. Son overrides Person by using vals - and thus you get the guarantee that nobody will change the fields in Son ever again.

From your example I assume that you still want to have a type of Person that can be modified. And you can do that using the MutablePerson class above, which does allow it's fields to be mutated.

Hope this helps !

like image 176
Marius Danila Avatar answered Sep 30 '22 14:09

Marius Danila