代码之家  ›  专栏  ›  技术社区  ›  user79074

如何更改case类的基类属性

  •  0
  • user79074  · 技术社区  · 6 年前

    采用以下代码:

    class A(val i: Int)
    
    case class B(str: String) extends A(1)
    
    val b = B("test")
    

    在我的场景中,我受到b的定义的限制,b的定义是不可更改的。我还希望避免重建B,因为我有许多这样的对象,它们的属性比本例中多得多。

    是否有任何方法可以为我创建一个新的B副本(使用反射或其他方式)和一个新的值?

    相当于:

    val b2 = b.copy(i = 2)
    

    注:问题是能否做到?最好的编程实践不是什么。

    3 回复  |  直到 6 年前
        1
  •  1
  •   Dima    6 年前

    您可以使用反射来实现这一点:

      val b = B("foo")
      val c = b.copy()
      println(b.i) // prints 1
      val field = classOf[A].getDeclaredFields.head
      field.setAccessible(true)
      field.setInt(c, 2)
      println(c.i) // prints 2
    

    但要注意,这不仅仅是“糟糕的编程实践”,而是 完全违反合同 .

    你的声明 case class B(s: Sting) extends A(1) 许诺 全部的 实例 B 总是 i 等于1,这是一个谎言。

    更不用说,有趣的事实 b == c 存在 true c.copy.i 1岁等。 不要这样做。

        2
  •  0
  •   SergGr    6 年前

    如果你定义了 B 那样。但是这个代码适用于我:

    class A(val i: Int)
    
    case class B(str: String, override val i:Int=1) extends A(i)
    
    val b = B("test")
    val b2 = b.copy(i = 2)  
    

    P.S.从技术上讲,你可以不做任何修改就复制,然后编辑 i 使用反射,但这不是一个好主意。

        3
  •  0
  •   Tim    6 年前

    您可以这样做:

    val b2 = new B(b.str) { override val i = 2 }
    

    缺点是你必须重新构建 B 从参数来看,如果有很多的话,可能会很麻烦。