代码之家  ›  专栏  ›  技术社区  ›  Joa Ebert Emran

Case class copy()方法抽象

  •  12
  • Joa Ebert Emran  · 技术社区  · 14 年前

    sealed trait Op case class Push(value: Int) extends Op case class Pop() extends Op .

    第一个问题:没有参数/成员的case类没有定义copy方法。你可以在REPL里试试这个。

    scala> case class Foo()
    defined class Foo
    
    scala> Foo().copy()
    <console>:8: error: value copy is not a member of Foo
           Foo().copy()
                 ^
    
    scala> case class Foo(x: Int)
    defined class Foo
    
    scala> Foo(0).copy()
    res1: Foo = Foo(0)
    

    case类来定义复制方法。

    第二个问题:我有办法 def ops: List[Op] 我想复制所有的行动 ops map { _.copy() } . 如何在中定义copy方法 Op 特质?如果我说 def copy(): Op . 但是,由于所有copy()方法都只有可选参数:为什么这是不正确的?那么,我该怎么做呢?通过使另一个方法 def clone(): Op 到处写 def clone() = copy() 所有的案例类?我希望不是。

    5 回复  |  直到 14 年前
        1
  •  9
  •   Mirko Stocker    14 年前
    1. 对于没有任何参数的case类,编译器生成的copy方法有什么好处?这只会返回一个新的Foo,而不会复制任何内容。
    2. quote Lukas Rytz
    只有在类中没有直接定义或继承的名为“copy”的成员时,才会生成copy方法。
        2
  •  12
  •   Daniel C. Sobral    14 年前

    你好像很困惑 copy 具有 clone 复制 就是做一个 几乎 一模一样,但有些改变。可能是什么取决于case类的参数,因此不可能将其作为一个公共方法。

    如果是 case class X() ,没有什么意义 复制 方法,因为没有什么可以改变的。

    克隆

        3
  •  2
  •   missingfaktor Kevin Wright    14 年前

    sealed trait Op 
    case class Push(value: Int, context:String) extends Op
    case class Pop(context:String) extends Op
    
    val stackOps = List(Push(3, "foo"), Pop("foo"))
    
    def copyToContext(newContext:String, ops:List[Op]): List[Op] = {
        // ... ?
    }
    
    val changedOps = copyToContext("bar", stackOps)
    
    // would return: List(Push(3, "bar"), Pop("bar"))
    
        4
  •  2
  •   Przemek Pokrywka    13 年前

    正如Mirko正确指出的,您不能真正地抽象over copy方法。我支持Daniel的观点,即克隆可能是您想要的,尽管我会用一些帮助程序代码来包装它以简化样板文件。

    您可以使用复制功能定义一个mixin trait,然后将其混合到case类中:

    trait ClonableAs[T] extends Cloneable { this: T => 
      def makeClone() = super.clone().asInstanceOf[T]
    }
    
    case class Foo(i: Int) extends ClonableAs[Foo]
    
    List(Foo(1), Foo(2), Foo(3)).map(_.makeClone())
    

    这样,您就不用为每个case类添加相同的方法,而是让它们扩展helper特性,从而使它们更干净,并为您节省一些击键。

    另一方面,克隆对不可变对象没有意义,因此我推断类的状态是可变的。我建议你重新考虑,如果你真的不能使他们不变,并使用这种类型的克隆只有在最后手段。不变性将保护您免受一类错误的影响。

        5
  •  1
  •   Ben Lings    14 年前

    为什么需要创建案例类实例的相同副本?Case类在默认情况下是不可变的,因此可以安全地共享。

    在任何情况下,我不认为你能用默认参数做你所要求的:

    scala> trait Op { def copy():Op }          
    defined trait Op
    
    scala> case class Op1(v:Int) extends Op    
    <console>:6: error: class Op1 needs to be abstract, since method copy in trait Op of type ()Op is not defined
           case class Op1(v:Int) extends Op
    

    编译器不会创建具有定义类中所有可选参数组合的方法。默认值插入到调用方法的位置。