土岐です。
# ruby-listにメールを出すのはひさしぶりです。
# 修論に追われてたもんで...

{Date} Fri, 10 Mar 2000 22:03:09 +0900
{Subject} [ruby-list:21297] Re: 引数コピーとオブジェクト指向
{Message ID} <xnmg0tzq8ok.wl / nancy.coop.nagoya-u.ac.jp>
ogino / coop.nagoya-u.ac.jp wrote...

ogino> name = 'John'
ogino>   :
ogino> john = Person.new (name.dup)
ogino>   :
ogino>   :
ogino> name.sub! (....)

このコードを見てふと気づいたことがあったので、
ちょっと自分なりにまとめてみました。
わたしはこの手のオブジェクトの状態を変化させるような
コードを書くとき、いつも次の様にしています。

name = 'John'
  :
john = Person.new (name)
  :
  :
name = name.dup
name.sub! (....)

オブジェクトの参照を増やす所(Person.new (name))ではなくて、
オブジェクトの状態を変化させる手前(name.sub! (....))の所に
dupを入れているわけです。

普段はほとんど何も考えずに習慣的にこの様なコードを
書いてしまうのですが、なんでこう書くようになったのか
ちょっと自己分析してみると

  1. ある変数の参照しているオブジェクが、他の変数からも
     参照されているかどうかを知ることは一般的にはできない。
  2. 状態が変化した後のオブジェクトを必要としているのは、
     オブジェクトに破壊的な操作を実行している場所だけである。
  3. 変数が参照しているオブジェクを複製して現在の状態を
     抽出し、複製されたオブジェクトに破壊的な操作を加えるのが
     最も確実で安全である。

と考えた結果のようです。
この方針だと、メソッドの操作がオブジェクトに対して
破壊的であるかどうかだけを知っていれば割と機械的に対処できます。
なので(少なくともわたしにとっては)あまり負担ではないです。

はじめからここまで詰めて考えていたわけではないんですけど、
変数の指す先にはオブジェクトがあって、
そのオブジェクトは他の変数からも参照されている可能性があって、
変数からオブジェクトへメソッド(メッセージ?)を送ると
オブジェクトが何らかのリアクションを起こして、
場合によってはオブジェクトの状態が変化するんだ...
といつも漠然と意識していたら、自然とこんな習慣が
身に付いてしまったように思います。

それで荻野さんが問題にされているカプセル化についてですが、
確かにインスタンス変数のオブジェクトが他の外部の変数と
共有されているとカプセル化が壊れるかもしれなくて
心配だというのも分かるんですが、
逆に共有されていることを利点として使いたい場合もあるし、
共有が必要無い場合は(少なくともわたしは)上で説明した方針で
今迄間に合ってきたので、あまり深刻に心配したことは無いです、
わたしの経験上。
# わたしの経験がどこまで一般的に適用できるか、というのは
# これはこれで問題ですけど(汗)

結局

ogino> したがって、ドキュメントをよく読み内部を把握してから使うか、または引数
ogino> に与えるときに複製を与えるなり、または変化させないように name.sub! で
ogino> はなく name = name.sub を使用するなりするべきだということですね。逆に
ogino> 他の人(または一年後の自分)につかってもらうことを想定するライブラリ内に
ogino> おいては dup をする必要は普通はない。それは利用者の責任である、と。こ
ogino> れを Ruby 流と呼ぶ?

こうゆうことなんですが、まあ割と機械的に対処できる(?)ので
使う側にそれほど負担にはならないよ、ということです。

--------------------------------------------------
土岐 仁謙    神戸大学物理高エネ研 M2
http://www.freedom.ne.jp/toki/