2010/11/6 Y. NOBUOKA <nobuoka / r-definition.com>:

> 信岡です。
>
> 私も遠藤さんと同じような理解をしていて、大別すると
>
> 1. クラスで定義されている private インスタンスメソッド、およびクラスとモジュールで定義されている private な特異メソッドは非公開にしたい
> 2. モジュールで定義されている private インスタンスメソッドはミックスインして関数として使って欲しい
>
> と分けられる思っています。 (組み込みクラスの private メソッドは別として。)

この分類は・・・どうだろう。
いちおう確認しますが、2. は非公開にはしないという意味ですよね。
それだと、module内で非公開なメソッドを定義したい場合はどうするのでしょうか。
Rubyのmoduleは実装が継承できることが特徴なので、moduleで定義されてても
非公開にしたいケースは十分ありうると思います。


> ここで、関数として使って欲しいメソッド (2 番の用法) は
> module_function として定義すると考えると、private として明示的に宣言
> する場合は全て非公開扱いになるかなぁ、と。

「private」だけで判断するのではなく、他の要素 (module_functionなど) も
含めて、非公開かどうかを判断する、ということですよね。
まあそれでもいいのかもしれませんが、望ましい姿とはちょっと思えません。


> ただし、「非公開」 の意味が桑田さんが考えているものと違っていて、桑田さんは
>> #いちおうここでは「非公開」=「使ってほしくない」という意味で考えてます。
> と考えておられますが、私は 「非公開」 = 「外部オブジェクト (自分以外
> のオブジェクト) からは呼び出せない」 という意味で考えています。(つま
> り、オブジェクトにとって非公開なのか、プログラマにとって非公開なのか
> の違い、でしょうか。)

僕は、「外部オブジェクト (自分以外のオブジェクト) からは呼び出せない」ことは
非公開とは関係ないと思ってます。
先のメールに例として書いたように、非公開なメソッドを外部オブジェクトから
呼び出したいケースがあるので。

def _inspect2(buf, level)   # 非公開にしたいメソッド
  buf << ("  " * level) << "- #{@value}\n"
  @left_node._inspect2(buf, level+1)   # でも外部オブジェクトから呼び出したい
  @right_node._inspect2(buf, level+1)
  # もちろん @left_node.__send__(:_inspect2, buf, level+1) とするのは可能
end


> レシーバを指定した呼び出しを禁止する、ということは、そのメソッドを呼
> び出せるオブジェクトは自分自身だけである、ということになります。例え
> ばあるクラス C のインスタンス c1 があったとして、c1 の外部から c1 の
> プライベートメソッドは c1.method() の形式では呼び出すことができません。
> これは 「(オブジェクトの外部から) 使って欲しくない」という目的を達成
> する手段として妥当だと思います。

上の例に示したように、僕は妥当だとは思いません。


> ただ、この方法だとクラス C のサブクラス CSub の中のメソッドからクラス
> C の private メソッドを呼び出したりすることはできるので、桑田さんが考
> えている 「非公開」 よりも緩い制限にはなっていると思います。
>
> Ruby の private は、単にそのクラスをインスタンス化して使うようなプロ
> グラマに対しては非公開ですが、そのクラスのサブクラスを作って使うよう
> なプログラマに対しては公開されている、(Java の protected に近い) と考
> えられると思います。

確かに。サブクラスで呼び出せるのに「private」という名前をつけたのは
かなり誤解を招きますね。

--
regards,
makoto kuwata