不変型にコピー メソッドを実装し、新しいインスタンスを返すことは理にかなっていますか? それとも、現在のインスタンスにする必要がありますか?
どうせタイプは変わらないと思っていたのになんでコピーするの?誰も5番をコピーしないようにね。
不変型にコピー メソッドを実装し、新しいインスタンスを返すことは理にかなっていますか? それとも、現在のインスタンスにする必要がありますか?
どうせタイプは変わらないと思っていたのになんでコピーするの?誰も5番をコピーしないようにね。
それが理にかなっている特定のケースがあります。Java 文字列が良い例です。文字列が Java で作成されると、文字のバッキング配列 (a char[]
) への参照が含まれます。char配列へのオフセットと文字列の長さを知っています。部分文字列を作成すると、それは同じバッキング配列を参照します。次のコードを検討してください。
String x = buildVeryLongString();
String y = x.substring(0, 5);
// Use y a lot, but x is garbage collected
がまだシステムにあるということは、によって使用されy
たオリジナルがまだ必要であることを意味します。つまり、必要以上のメモリを使用しています。コードを次のように変更した場合:char[]
x
String x = buildVeryLongString();
String y = new String(x.substring(0, 5));
その後、データを新しい にコピーすることになりますchar[]
。x
とy
の寿命がほぼ同じである場合、このアプローチは (2 つのコピーを持つことによって) メモリを浪費しますが、 が のx
前にガベージ コレクションされる場合y
、大きな違いが生じる可能性があります。
辞書から単語を読み取るときに、実際の文字列で同様の例に出くわしました。デフォルトでBufferedReader.readLine()
は、 は行の開始に 80 文字のバッファを使用します。そのため、 によって返される (空でない) 文字列は、少なくとも 80 文字readLine()
の配列を参照します。char[]
1 行に 1 単語の辞書ファイルを読んでいる場合、それは多くの無駄なスペースです!
これは単なる例ですが、2 つの不変オブジェクトの違いを示しています。2 つの不変オブジェクトは意味的には同じですが、他の点では異なる特性を持っています。これは通常、不変型をコピーしたい理由の中心にありますが、それでもやりたいことはかなりまれです。
.NET では、文字列の格納方法が多少異なります。文字データは、別の配列ではなく、文字列オブジェクト自体に保持されます。IntPtr
(私が知る限り、.NET で可変サイズの型は配列、文字列、および3 つだけです。)ただし、文字列の "バッファー" は必要以上に大きくなる可能性があります。例えば:
StringBuilder builder = new StringBuilder(10000);
builder.Append("not a lot");
string x = builder.ToString();
によって参照される文字列オブジェクトx
には、巨大なバッファがあります。最後の行を に変更するbuilder.ToString().Copy()
と、大きなバッファーがすぐにガベージ コレクションの対象になり、代わりに小さな文字列が残ります。繰り返しますが、これを無条件に行うのは悪い考えですが、場合によっては役に立ちます。
技術的には、整数は値型であるため、常にコピーされます。:)
とはいえ、不変オブジェクトのコピーを作成しても意味がありません。他の人が提供する文字列の例は、それらのクラスによる抽象化の漏れに対する応急処置のようです。
オブジェクト (クラス) を意味していると仮定します。
不変オブジェクトのクローンを作成するには、いくつかの疑わしい理由があります。
readonly
によってフィールドさえも変更される可能性があります)-おそらく、いくつかの超セキュリティ意識の高いコードの場合通常の不変オブジェクトは、関連付けられたオブジェクトも不変であることを意味しないため、議論を拡張してディープクローニングを検討すると、より合理的になります。ディープ クローンはこれを修正しますが、別の考慮事項です。
おそらくリモートシナリオが私ができる最善のことだと思います...
Java の String クラスには次のようなものがあります。
String(String original)
Initializes a newly created String object so that it represents the same
sequence of characters as the argument; in other words, the newly created
string is a copy of the argument string.
そして.NetにCopy()
は同じことをするメソッドがあります。
両方のフレームワークは私より賢い人によって設計されたので、正当な理由があるに違いありません - 誰かが参照に関して異なるが同じ値を持つ文字列を必要とすることがあります。
それがいつになるかはわかりません...
不変オブジェクトに「コピー」操作を提供することは理にかなっていますか?
いいえ。
(他の回答には他にも興味深い議論がたくさんありますが、短い回答を提供すると思いました。)
オブジェクトが Clone() メソッド (または同等のメソッド) を必要とするインターフェースを実装する必要がある場合は、「これを返す」ことは問題ありません。
不変型の利点の 1 つは、インターンできることです (Java 文字列など)。避けられるのであれば、確かに余分なコピーを作成するべきではありません。