4

.cloneScala で自分のオブジェクトを作成する方法を理解しようとしています。

これはシミュレーション用であるため、変更可能な状態が必須であり、そこからクローン作成の必要性が生じます。シミュレーション時間を進める前に、状態構造全体を複製します。

これは私の現在の試みです:

abstract trait Cloneable[A] {
  // Seems we cannot declare the prototype of a copy constructor
  //protected def this(o: A)    // to be defined by the class itself

  def myClone= new A(this)
}

class S(var x: String) extends Cloneable[S] {
  def this(o:S)= this(o.x)    // for 'Cloneable'
  def toString= x
}

object TestX {
  val s1= new S("say, aaa")
  println( s1.myClone )
}

を。上記がコンパイルされないのはなぜですか。与えます:

エラー: クラス タイプが必要ですが、A が見つかりました
  def myClone= 新しい A(これ)
                   ^

b. def this(o:A)トレイトを使用するクラスがそれを提供する必要があることが示されるように、トレイトでコピー コンストラクタ () を宣言する方法はありますか。

c. と言うメリットはありますabstract traitか?

最後に、これらすべてに対するより良い方法、標準的な解決策はありますか?

Javaのクローン作成について調べました。このためではないようです。また、Scalacopyはそうではありません。これはケース クラス専用であり、ミュータブルな状態を持つべきではありません。

助けと意見をありがとう。

4

3 に答える 3

9

特性はコンストラクターを定義できません (そして、特性に影響を与えるとは思いませんabstract)。

clone メソッドを実装するだけでなく、コピー コンストラクターを使用する必要がある理由はありますか? クラスで [A] 型を宣言する必要がなくなる可能性がありますが、少なくとも自己型を宣言したので、コンパイラは型がクラスと一致することを確認します。

trait DeepCloneable[A] { self: A =>
    def deepClone: A
}

class Egg(size: Int) extends DeepCloneable[Egg] {
    def deepClone = new Egg(size)
}

object Main extends App {
    val e = new Egg(3)
    println(e)
    println(e.deepClone)
}

http://ideone.com/CS9HTW

于 2012-10-23T14:16:29.177 に答える
3

型クラスベースのアプローチを提案します。これにより、既存のクラスを複製可能にすることもできます。

class Foo(var x: Int)

trait Copyable[A] {
  def copy(a: A): A
}

implicit object FooCloneable extends Copyable[Foo] {
  def copy(foo: Foo) = new Foo(foo.x)
}

implicit def any2Copyable[A: Copyable](a: A) = new {
  def copy = implicitly[Copyable[A]].copy(a)
}


scala> val x = new Foo(2)
x: Foo = Foo@8d86328

scala> val y = x.copy
y: Foo = Foo@245e7588

scala> x eq y
res2: Boolean = false
于 2012-10-23T16:34:31.367 に答える
3
  • を。のような型パラメーターを定義すると、コンパイル フェーズ後にA消去されます。

    これは、コンパイラが型パラメーターを使用して正しい型を使用していることを確認することを意味しますが、結果のバイトコードにはA.

    これは、実行時にこの情報が失われるため、コード内で実際のクラスとして使用することはできずA、「型参照」としてのみ使用することも意味します。

  • b&c。特性は、定義によりコンストラクターパラメーターまたは補助コンストラクターを定義できません。定義により抽象的でもあります。

    あなたができることは、具体的な実装のインスタンス化時に呼び出される特性本体を定義することです

Cloneable 別の解決策の 1 つは、 typeclassを定義することです。詳細については、この件に関する多くのブログを見つけることができますが、具体的な提案はありません。

scalazには、このパターンを使用して構築された大きな部分があります。おそらくそこからインスピレーションを得ることができます: OrderEqual、またはShowを見て、その要点をつかむことができます。

于 2012-10-23T14:36:21.000 に答える