0

次の状況を考慮してください。

組み込み(モデム)デバイス用のJavaプログラムを作成します。SDKはCloneableを提供していません。したがって、私はclass GsmSignalStrengthメソッドclone()にありますが、それはからではなく、Object.clone()「私の」実装です。GsmSignalStrengthこれが便利で正しいのか、コメントのようにでコピーコンストラクターを使用する必要があるのか​​知りたいのですが。StateMachineに別のGsmSignalStrengthオブジェクトを作成する必要があるため、コピーコンストラクターの利点はわかりません。

これが私のコードです...

ファイル1"Status.java":

class Status
{
    Status(GsmSignalStrength gsmSignalStrength)
    {
        initClass(gsmSignalStrength);
    }

    GsmSignalStrength gsmSignalStrength;

    private void initClass(GsmSignalStrength gsmSignalStrength)
    {
        this.gsmSignalStrength = gsmSignalStrength;
    }
}

ファイル2「GsmSignalStrength」:

class GsmSignalStrength
{
    GsmSignalStrength(byte signalStrength)
    {
        initClass(signalStrength);
    }

    GsmSignalStrength()
    {
        initClass(100);
    }

    byte value;

    public void copyTo(GsmSignalStrength destination)
    {
        destination.value = this.value;
    }

    public GsmSignalStrength clone()
    {
        GsmSignalStrength clonedValue = new GsmSignalStrength();

        this.copyTo(clonedValue);

        return clonedValue;
    }

    /* With copy constructor
        GsmSignalStrength(GsmSignalStrength gsmSignalStrength)
        {
            gsmSignalStrength.value = value;
        }
    */

    private void initClass(byte signalStrength)
    {
        this.value = signalStrength;
    }
}

ファイル5「GsmModemHandler」:

class GsmModemHandler
{
    GsmModemHandler()
    {
        initClass();
    }

    private GsmSignalStrength m_gsmSignalStrength;

    GsmSignalStrength getGsmSignalStrength()
    {

        ...bla...

        return m_gsmSignalStrength;
    }

    private void initClass()
    {
        m_gsmSignalStrength = new GsmSignalStrength();
    }
}

ファイル4「StateMachine」:

class StateMachine
{
    StateMachine(GsmModemHandler gsmModemHandler)
    {
        initClass(gsmModemHandler);
    }

    private GsmModemHandler m_gsmModemHandler;

    void doSomething()
    {
        GsmSignalStrength gsmSignalStrength = m_gsmModemHandler.getGsmSignalStrength();
        Status xy = new Status(gsmSignalStrength.clone());

        /* With copy constructor

            GsmSignalStrength gsmSignalStrengthCopy = new GsmSignalStrength(gsmSignalStrength);
            Status xy = new Status(gsmSignalStrengthCopy);
        */
    }

    private void initClass(GsmModemHandler gsmModemHandler)
    {
        m_gsmModemHandler = gsmModemHandler;
    }
}
4

2 に答える 2

4

あなたは何持ってるそのコメントにあった、

GsmSignalStrength(GsmSignalStrength gsmSignalStrength)
    {
        gsmSignalStrength = this;
    }

コピー コンストラクターではありません。この線

gsmSignalStrength = this;

を指すようにメソッドローカル参照を移動するだけなので、まったく効果がありませんthis

機能する「コピーコンストラクター」は次のようになります

GsmSignalStrength(GsmSignalStrength gsmSignalStrength)
    {
        this.value = gsmSignalStrength.value;
    }

ポイントは、元のオブジェクトと同じメンバー変数を持つ独立したオブジェクトを作成することです。

また、C++ とは異なり、次のように記述します。

object1 = object2;

コピー コンストラクターを呼び出しません。参照をコピーするだけで、同じオブジェクトを指す 2 つの参照が作成されます。新しいオブジェクトを作成する場合は、コンストラクターを明示的に呼び出す必要があります。

object1 = new GsmSignalStrength( object2 );

「役に立たない」かどうかは、アプリケーションによって異なります。コピー コンストラクター、clone()メソッド、および独自のcopyToメソッドはすべて、同じ基本的なタスクを実行します。コンストラクターまたは を使用しclone()て新しいオブジェクトを作成するか、新しいオブジェクトを作成して使用copyToすることができます。やりたいことを行う方法を 1 つ選んで、それを使い続けることができます。

于 2012-04-11T15:47:10.210 に答える
1

クローンを使用するだけでよいと思いますが、慎重に行ってください。Joshua Bloch の「Effective Java」では、clone は弱いインターフェイスであり、アクティビティをサポートするためのメソッド コントラクトを提供しないため、clone は慎重に使用する必要があると述べています。また、行儀の良いスーパークラスのクローン動作に依存しています (つまり、スーパークラスは、super#cloneクラス コンストラクターを使用してオブジェクトを作成するのではなく、クラス コンストラクターを使用します (間違ったクラスのインスタンスを作成します)) 。あなたのファイル 2の例 - 非最終クラスでは、複製サブクラスを壊します。

クローン (および各スーパークラス クローン) は、すべての ivar の完全なコピーを提供する必要があることに注意してください。配列やリストなどのディープ コピーを作成する必要がある場合があることに注意してください。つまり、配列の新しいインスタンスを作成し、独自のリストに要素の新しいコピーを追加します。これは「浅いコピー」ではなく「深いコピー」です。クローンは元のオブジェクトと同じデータを共有すべきではありません (ただし、これについてはケースバイケースで議論することができます)。

また、コピーが何をするか (深いコピーと浅いコピーなど) が十分に文書化されている限り、コピー コンストラクターの概念に問題はないと思います。

あなたの例のサンプルコードは次のようになります。

public class GSMSignalStrength implements Cloneable {
    ...
    public Object clone() throws CloneNotSupportedException {
        GSMSignalStrength result = (GSMSignalStrength)super.clone();
        result.setValue(this.value);
        result.setAnyOldArray(this.deepCopyMyAnyOldArray());
        ...
    }
    ...
}

お役に立てれば!

psジェネリックに関してCloneableはレビューされていないため、その周りにタイプセーフを追加できる場合があります。実際、クローン可能を実際に実装したことはまったくありません。過去に (Obj-C の世界では、グラフィックス パッケージで多くの cop-constructing を行い、オブジェクト グラフと密接に結びついていました。V.複雑な。

于 2012-04-11T16:07:32.513 に答える