From: Makoto Kuwata Date: 2010-11-06T13:12:44+09:00 Subject: [ruby-list:47608] Re: Rubyでも「private」イコール「非公開」? 桑田です。お返事ありがとうございます。 2010/11/4 Yusuke ENDOH : > > 完全に違う話ではなく、目的と手段の関係にあると思っています。 > > 目的: 使ってほしくないことを伝えたい (普通には使えなくしたい) > 手段: レシーバを指定した呼び出しを禁止する これは、目的のための手段としては正しくないように思います。 > > ただしこの手段は、異なる目的のためにも使われています。 > > 目的: 関数のように使ってほしいことを伝えたい > 手段: レシーバを指定した呼び出しを禁止する これは正しい手段だと思います。 > > どっちの意味なのかはユーザが空気を読む必要がありますが、大まかに > 以下のコンセンサスがあると思っています。 > > 1. Kernel クラスに属す private メソッド > => グローバル関数として公開 (p など) > > 2. Module や Class クラスに属す private メソッド > => 呼称は知らないが公開 (Module#attr_reader など) > > 3. module_function として定義されているメソッド > => モジュール関数として公開 (Math#sin など) > > 4. それ以外 > => 非公開 この分類は面白いですね。 これだと「privateメソッドが非公開を意味することもある」という解釈で いいのでしょうか。少なくとも「privateメソッド=非公開」ではないですよね。 > > ただし、「レシーバを指定した呼び出しを禁止する」のはあくまで手段 > なので、ライブラリの作者がその手段を他の用途に使うのも、勝手だと > 思います。 はい。 > >> 実際、ヘルパーメソッドなどはprivateだけど絶賛公開していることも >> ありますし、 > > ヘルパーメソッドが何かよくわからないので見当違いかもしれないですが、 > 例えば ERB::Util#h とかは module_function になっています。 > 上記分類の 3. ということでしょうか。privateだけどmodule_functionなので 非公開ではなく公開である。 > >> 逆に公開したくないんだけどレシーバつけて呼び出すから >> privateはつけられないようなメソッドもあります。 > > C++ の friend が欲しいケースですかね。これは別の問題だと思います。 別にfriendのことではないです。自分のクラスでしか使わないから非公開に したいけど、レシーバは省略しないケースを想定しています。 class Node def inspect2 # for debug buf = '' level = 0 _inspect2(buf, level) buf end def _inspect2(buf, level) # 非公開にしたいメソッド buf << (' ' * level) << '- ' << @value @left_node._inspect2(buf, level+1) # でもレシーバは省略しない @right_node._inspect2(buf, level+1) # @right.__send__(:_inspect2, buf, level+1) とできなくもないけど・・・ end ... > > > ・定数に private をつけると、それは「スコープが指定できない」ことになる > ・メソッドに private をつけると、それは「レシーバが指定できない」ことになる > > ですね。 なるほど。 ・private定数は Foo::Bar で指定できず、Bar で指定する ・privateメソッドは foo.bar() で指定できず、bar() で指定する と考えれば、似ていると思えてきました。 すくなくとも C の static よりはひどくない。 >> ・非公開にするものは :nodoc: をつける (privateの有無は問わない) > > :nodoc: と付ける風習自体はよいことだと思いますが、private のように > プログラミング言語の機能として表明できればよりよいと思います。 はい、僕もその意見については賛成であり、機能の追加には反対ではありません。 単に、Ruby における「private」という用語が「非公開」を意味するかどうかを 確認したかっただけです。 で、結局は最初のほうで出てきた > 目的: 使ってほしくないことを伝えたい (普通には使えなくしたい) > 手段: レシーバを指定した呼び出しを禁止する が妥当かどうか、というのがポイントなのかなと思います。 #いちおうここでは「非公開」=「使ってほしくない」という意味で考えてます。 つまり、レシーバつきの呼び出しを禁止することが、Rubyでは「非公開(使って ほしくない)」を意味するかどうかです。 結局は上の分類にあったように、privateでも公開されているものがあるから、 「privateだからといって必ずしも非公開を意味するわけではない」という、 あまりすっきりしない結論になっちゃうと思います。 そのため、あるメソッドが非公開であることを表明したい場合は、privateという 言語機能に頼らず、地道に :nodoc: をつけるしかないのかなと思います。 #これはメソッドの場合ですが、定数の場合にどうなるかはよくわかってません。 -- regards, makoto kuwata