5

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.

3
  • The fields are already mutable in Son. Do you maybe mean the opposite? or what is it that you want to achieve really? Commented Nov 30, 2012 at 14:33
  • Hi, I answered you in Update #2 Commented Nov 30, 2012 at 14:57
  • i don't see what you are getting by trying to hide the parameters of Person's constructor. if you change Person to trait, then you just have Son with Person and you have access to it's fields Commented Nov 30, 2012 at 15:37

2 Answers 2

16

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 !

Sign up to request clarification or add additional context in comments.

Comments

6

You have to name the params different, because otherwise the methods in the body of son will try to access the params and not the fields in the Person class. Scala will automatically create fields for the params if you access them in the body. It will work, when you do something like this (which also is a commonly used pattern):

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.