【问题标题】:Modify one value in a Scala class constructor in a concise way以简洁的方式修改 Scala 类构造函数中的一个值
【发布时间】:2017-07-09 01:05:20
【问题描述】:

如果我想修改构造函数中的一个参数。

在 Scala case 类 中,apply 方法将被覆盖两次。除非 apply 适用(无双关语)辅助构造函数。 与

相关

如何修改来自构造函数的单个输入?

标准:

  • 该类必须保存不可变数据。所有数据都必须是可访问的。

  • 请注意,它不必是案例类。

  • 另外,不需要使用apply方法。

  • 没有额外的未使用参数。在下面的示例中,_fistName 仍可访问但未使用。

案例类人( 姓氏:字符串, _fistName:字符串,...) { 懒惰的 val 拳头名 = _fistName.toLowerCase }

【问题讨论】:

    标签: scala case-class


    【解决方案1】:

    这里有两种简单的方法。

    使用类:

    class Person(first: String, last: String) {
      val firstName = first.toLowerCase
      val lastName = last.toLowerCase()
    }
    
    val person = new Person("Adam", "Smith")
    println(person.firstName + " " + person.lastName) // adam smith
    

    使用 trait + 对象的 apply():

    trait Person {
      val firstName: String
      val lastName: String
    }
    
    object Person {
      def apply(first: String, last: String) = new Person {
        override val firstName: String = first.toLowerCase
        override val lastName: String = last.toLowerCase
      }
    }
    
    val person = Person("Adam", "Smith")
    println(person.firstName + " " + person.lastName) // adam smith
    

    请注意,类必须使用 new 实例化,而特征(使用 apply() 创建)则不需要。

    为什么没有案例类?好吧,它们被设计为用作 ADT(抽象数据类型)。基本上,它们被认为是一些没有任何逻辑的数据的容器。这就是为什么他们开箱即用地获得apply()。如果要覆盖它,则意味着您的类没有案例类的语义。

    我可以看到@prayag 努力帮助您将其强制纳入案例类,但说真的,如果它不必是一个(并且您在问题中这么说),那么不要做一个。

    【讨论】:

    • 我喜欢使用类的方式。它很优雅。如果你有很多参数要传递给构造函数。有没有办法只改变一个变量而不是复制其余的?我喜欢案例类的简洁性
    • 是的,只要在构造函数的前面加上val就行了。案例类会自动获得。例如。 class Person(first: String, val lastName: String) { val firstName = first.toLowerCase }
    • 好的,我明白了。但我想避免重复明显的: class Person(first: String, last: String, x: Int, y: Int, ... ) val lastName = last val lastName = last, val x = x , val y = y ...我想没有捷径
    • 你不需要val y = y。我之前评论中的代码有效。在lastName 前面加上val 意味着它可以公开访问。
    • 我编辑了上面的评论。抱歉,我无法在评论中格式化为代码
    【解决方案2】:

    您发布的参考资料似乎也有很多答案。

    我能想到的两种简单方法

    1. 将其设为 abstract case class 并定义可改变您想要的值的伴随对象

    2. 将case类的成员定义为var并对其进行变异。

    例如。 (使用scalatest

     class CaseClassSpecs extends FunSpec {
    
       describe("case class modify") {
    
         it("APPROACH 1 : modifies abstract case class member") {
    
          object Item {
            def apply(itemId: String, itemName: String) :Item = new Item(itemId.toLowerCase, itemName) {}
          }
    
          abstract case class Item private (val itemId: String, itemName: String)
    
          val item1 = Item("SKU-ONE", "Shirts")
    
          assert(item1.itemId == "sku-one")
          assert(item1.itemName == "Shirts")
        }
    
         it("APPROACH 2 : modifies case class member which is var") {
    
          case class Item (var itemId: String, itemName: String) {
            itemId = itemId.toLowerCase()
          }
    
          val item1 = Item("SKU-ONE", "Shirts")
    
          assert(item1.itemId == "sku-one")
          assert(item1.itemName == "Shirts")
        }
       }
      }
    

    【讨论】:

    • 我不知道谁对你的答案和我的问题投了反对票。但我赞成你的回答。我提供的链接都没有给我答案。
    • 'val'修饰符对于case类主构造函数的参数是多余的。
    猜你喜欢
    • 1970-01-01
    • 2012-03-11
    • 1970-01-01
    • 2015-09-27
    • 1970-01-01
    • 2023-04-09
    • 2011-12-18
    • 2012-01-28
    • 2011-01-18
    相关资源
    最近更新 更多