【问题标题】:Scala: Extend concrete class with constructor parametersScala:使用构造函数参数扩展具体类
【发布时间】:2012-11-18 18:41:12
【问题描述】:

我有这个具体的类:

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

我想创建另一个扩展 Person 的类:

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

好的。 但我确实希望 Son 的构造函数中的字段必须是 var 而不是 val。 我该如何解决?字段必须保留构造函数参数。

更新 #2

我的问题如下: 如果我在 Son 中定义一个方法,如果我将值更改为 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")
}

Son 中的姓名和姓氏属于 val 类型。

【问题讨论】:

  • Son 中的字段已经是可变的。你的意思可能是相反的吗?或者你真正想要达到的目标是什么?
  • 嗨,我在更新 #2 中回答了你
  • 我看不到你试图隐藏 Person 构造函数的参数会得到什么。如果您将 Person 更改为 trait,那么您只有 Son 和 Person 并且您可以访问它的字段

标签: scala parameters constructor extend


【解决方案1】:

如果我理解正确,您希望 Son 中的 namesurname 字段是不可变的,而不是 Person 中的字段,它们是 vars。

这根本不可能。唯一的方法是覆盖:

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)

在 Scala 中,您不能用 val 覆盖 var - 原因很明显 - subclasses can only override or add functionality to a superclass。如果我们允许 vals 覆盖 vars,我们将从父类中删除被覆盖字段的设置器。这打破了继承隐含的“is-a”关系。

你可以这样做:

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 现在是一个特征 - 它只是提供了一种获取 namesurname 的方法。 Son 使用 vals 覆盖 Person - 因此您可以保证没有人会再次更改 Son 中的字段。

从您的示例中,我假设您仍然希望拥有可以修改的 Person 类型。你可以使用上面的MutablePerson 类来做到这一点,它确实允许它的字段被变异。

希望这会有所帮助!

【讨论】:

    【解决方案2】:

    您必须将参数命名为不同的名称,否则son 主体中的方法将尝试访问参数而不是Person 类中的字段。如果您在正文中访问参数,Scala 将自动为参数创建字段。当你做这样的事情时它会起作用(这也是一种常用的模式):

    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")
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-09
      • 2013-11-15
      • 2017-09-12
      • 2013-03-16
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多