From: Akira Hayakawa Date: 2008-08-30T08:55:29+09:00 Subject: [ruby-list:45431] cloneの挙動について おはようございます。Akiraです。 cloneについて質問があります。 Javaでは、cloneはObjectでprotectedで定義されていて、 サブクラスでオーバーライドする必要があったと思いますが、 http://java.sun.com/javase/ja/6/docs/ja/api/ Rubyはどうなのだろうと思って、以下のコードを試しました。 class Name attr_accessor :name def initialize(name) @name = name end end class Man attr_writer :name def initialize(name) @name = name end def get_name return @name.clone end end a = Man.new(Name.new("Akira")) p a.get_name p a.get_name.name = "Brad Pitt" p a.get_name 結果は、Rubyに精通しているみなさんに言うまでもないかと思いますが、 Man#get_nameで.cloneをしていると、3つ目のa.get_nameで"Akira"の保護されたNameオブジェクトが返ります。 .cloneをしないと、私が"Brad Pitt"になってしまって、べ、べつに嬉しくなんかないんだからねっ! ところで、cloneした事で、Name内のnameというプライベートフィールドが保護されてしまっているのですが、 これはcloneがディープコピーだという事ではないのでしょうか?あるいは私の認識が間違っているだけでしょうか。 http://www.asahi-net.or.jp/~dp8t-asm/java/tips/ObjectCopy.html 変数をコピーしただけのシャローコピーであれば、2行目のa.get_name.nameでcloneしていたとしても値が変わってしまうと思うのです。 http://www.ruby-lang.org/ja/man/html/Object.html シャローコピーと書いてあるのですが、私の考えのどこに間違いがあるのでしょうか? こういうのを防御的コピーと言うと思いますが、 Rubyでは、返すオブジェクトを不変に保ちたい時はどういうイディオムを使うのでしょうか? 1)上のようにコピーして返す。 2)更新メソッドを持たないラッパークラスを作ってコンストラクタ引数に元のオブジェクトを入れて返す 3)ドキュメントとして、「不変のつもりで大事に使ってください」と書く。 -- Akira Hayakawa