【问题标题】:Adding functionality before calling constructor in extra constructor在额外构造函数中调用构造函数之前添加功能
【发布时间】:2014-06-27 00:16:10
【问题描述】:

是否可以在scala的额外构造函数中调用构造函数之前添加功能?

比方说,我有 User 类,并且想要获取一个字符串 - 并将其拆分为属性 - 将它们发送到构造函数:

class User(val name: String, val age: Int){
    def this(line: String) = {
       val attrs = line.split(",") //This line is leading an error - what can I do instead
       this(attrs(0), attrs(1).toInt)
    }
}

所以我知道我不能在发送到 this 之前添加一行,因为所有构造函数都需要调用另一个构造函数作为构造函数的第一条语句。

那我还能做什么呢?

编辑:

我有一长串属性,所以我不想重复line.split(",")

【问题讨论】:

    标签: scala


    【解决方案1】:

    我认为这是伴随对象和apply() 方法很好地发挥作用的地方:

    object User {
      def apply(line: String): User = {
        val attrs = line.split(",")
        new User(attrs(0), attrs(1).toInt)
      }
    }
    
    class User(val name: String, val age: Int)
    

    然后您只需按以下方式创建对象:

    val u1 = User("Zorro,33")
    

    此外,由于您无论如何都要公开nameage,您可能会考虑使用案例类而不是标准类,并采用一致的方式构造User 对象(不带new 关键字):

    object User {
      def apply(line: String): User = {
        val attrs = line.split(",")
        new User(attrs(0), attrs(1).toInt)
      }
    }
    
    case class User(name: String, age: Int)
    
    val u1 = User("Zorro,33")
    
    val u2 = User("Zorro", "33")
    

    【讨论】:

    • 你不需要仅仅为了隐藏新的目的而将它设为 case 类:将 private 用于构造函数,而在同伴中使用另一个 apply 方法
    【解决方案2】:

    丑陋但有效的解决方案#1:

    class User(val name: String, val age: Int){
        def this(line: String) = {
           this(line.split(",")(0), line.split(",")(1).toInt)
        }
    }
    

    丑陋但有效的解决方案#2:

    class User(val name: String, val age: Int)
    object User {
      def fromString(line: String) = {
         val attrs = line.split(",")
         new User(attrs(0), attrs(1).toInt)
      }
    }
    

    可以用作:

    val johny = User.fromString("johny,35")
    

    您可以使用apply 代替fromString,但这会导致混淆(在一种情况下您必须使用new,在另一种情况下您必须放弃它)所以我更喜欢使用不同的名字

    【讨论】:

    • 我想我会使用你的第二个解决方案,如果没有更好的解决方案......我看到 scala 有点令人失望
    • 您可以使用 patmat 使第二个解决方案更漂亮:line.split('.') match { case Array(a, b) => new User(a, b.toInt) }
    • @AlexIv 我更喜欢val Array(a, b) = line.split(","); new User(a, b.toInt) :-)
    【解决方案3】:

    另一个丑陋的解决方案:

    class User(line: String) {
      def this(name: String, age: Int) = this(s"$name,$age")
    
      val (name, age) = {
        val Array(nameStr,ageStr) = line.split(",")
        (nameStr,ageStr.toInt)
      }
    }
    

    但是使用伴随对象的方法可能更好。

    【讨论】:

      猜你喜欢
      • 2016-07-16
      • 2011-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-20
      • 2012-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多