- PR -

Object クラスの clone メソッドが protected なので使いづらい

投稿者投稿内容
うのきち
ベテラン
会議室デビュー日: 2003/02/17
投稿数: 55
投稿日時: 2003-07-12 11:17
引用:

oceanさんの書き込み (2003-07-11 20:28) より:
すでに凍ったスレッドだと思いますが、認識が改まったので追記させていただきます。

snip

Javaでこうできないのは、Cloneableがタグにすぎず、実際にはclone()を持っていないためです。なぜJavaがそのような設計にしたかは存じませんが・・・

以前の私の返答は、C++の影響でしょうか、Objectがclone()を持つことを前提にしていたところがありました。でも実際にC#の設計を見てみると、悪夢を統べるものさんの

引用:

「Objectクラスのインスタンスはcloneできない」ってのが正しいかと


が正しかったのかなと思えました。




多分Java作った人たちが、魔法のようにshallow copyをやろうとしたのが、失敗の始まりだったのではないかと思います。
ただ、C#形式も、どうなんでしょうね。確かに単純で素直な感じはするんですけど、
IClonebaleを実装したクラスを継承した時に、フールドが増えたら、必ずClone()をオーバーライドする事を注意しておかないといけない(なんとなく、C#なら、コンパイル警告が出そう)。
さりとて、Javaの魔法のshallow copyだって、結局フィールドによっては、deep copyしないといけない場合があって、そこが落とし穴になるし。

引用:

まだ、
class A
class B : ICloneable, A
がAの設計変更でICloneableを実装したとき、B::Clone()を変更しなくちゃいけないのでは?とか、疑問が残ってはいますが。。。




なるほど、Javaなら、B#clone()で、super.clone()を呼んでおけばokってことですね。
ocean
ベテラン
会議室デビュー日: 2003/07/06
投稿数: 65
投稿日時: 2003-07-12 13:40
引用:

多分Java作った人たちが、魔法のようにshallow copyをやろうとしたのが、失敗の始まりだったのではないかと思います。
ただ、C#形式も、どうなんでしょうね。確かに単純で素直な感じはするんですけど、IClonebaleを実装したクラスを継承した時に、フールドが増えたら、必ずClone()をオーバーライドする事を注意しておかないといけない



そうなんですよね、でも正直、Clone()をオーバーライドすることを忘れなければ、C#の方が単純さの分だけ勝っているんじゃないかと思ってました。でも、実際にオーバーライドしようとコードを組んでみたところ、B::Clone()の中でどうA::Clone()を呼び出したらいいのかわからないんです。A::Clone()が返すのはAのインスタンスで、それから??って感じで。Webで調べても出てこないし、下のようなコードなら出てきたんですが・・・

コード:

public virtual object Clone()
{
return new Attribute(m_name,m_value,m_delim);
}



悩ましい。

#追記

というか、本来こうするのが正しい使い方なのかも。
すみません、Java板なのを忘れているわけではないです。clone()がどうあるべきかという話で・・・


[ メッセージ編集済み 編集者: ocean 編集日時 2003-07-12 14:10 ]
うのきち
ベテラン
会議室デビュー日: 2003/02/17
投稿数: 55
投稿日時: 2003-07-13 10:34
C#に関しては全くの無知なので、完全にあてずっぽうですが、コピーコンストラクタを経由するとか。

C#の文法は、わかんないので、JavaにIClonableがあったとしたらということで、考えてみました。

コード:
interface IClonable {
    Object Clone();
}

class A implements IClonable {
    private int a;

    A(A opponent) {
        a = opponent.a;
    }

    public Object Clone() {
        return new A(this);
    }
}

class B extends A {
    private int b;

    B(B opponent) {
        super (opponent);
        b = opponent.b;
    }

    public Object Clone() {
        return new B(this);
    }
}


ocean
ベテラン
会議室デビュー日: 2003/07/06
投稿数: 65
投稿日時: 2003-07-13 16:34
引用:

うのきちさんの書き込み (2003-07-13 10:34) より:
C#に関しては全くの無知なので、完全にあてずっぽうですが、コピーコンストラクタを経由するとか。



ええ、そうです。すみません、私の書き込みではコンストラクタだと明示してませんでした。

引用:

C#の文法は、わかんないので、JavaにIClonableがあったとしたらということで、考えてみました。



うのきちさんの示されたコードの方が、今のJavaのclone()より美しいと感じます。このコードなら、親クラスにコピーコンストラクタがなくても、それを呼びさえしなければ(望ましいかどうかは別問題として)子クラスでのICloneableの実装を妨げませんし・・・

こうして欲しいなあ(無理か・・・)

スキルアップ/キャリアアップ(JOB@IT)