特異クラス
Ruby で特異メソッドを登録しておく場所。移譲先。実行モデルには「特異クラス」というものはないらしい。(ん、これは実体がないということではなく、実体はあるが単にアクセスする手段が用意されていないということか?)--sumim
class << object
self
end
のように記述して定義できる(実際には self のところに object にさせたい振る舞い等を記述する)。つまり特異メソッドをまとめて定義するためのものか?--sumim
疑問:
特異メソッドを持ったインスタンスのクラスは元の(つまりそのインスタンスを生み出すために new() したクラスのままか?--sumim
答え:
変わらずそのまま。obj=Object.new
obj.class
==> Object
def obj.a
"obj.a"
end
obj.a
==> "obj.a"
obj.class
==> Object
class << obj
attr :b, true
end
obj.b="obj.b"
obj.b
==> "obj.b"
obj2=Object.new
obj2.a
NameError: undefined method `a' for obj2
obj2.b
NameError: undefined method `b' for obj2
つまり、class << instance ... end でアクセスできるのは instance.class とは別のオブジェクト(おそらく無名のクラス)で、すなわちこれが特異クラスということか?--sumim
で、Ruby のクラスメソッドはクラスの特異メソッドなので、通常(Smalltalk で)はメタクラスがすることを特異クラスが担当しているというで「特異クラスはメタクラス」というような表現が使われることがあるということかしらん。ちなみに class() でアクセスできる(たとえば、Object.class )通常のクラスのクラス(メタクラスに相当)は Class である。--sumim
特異クラスは、まず直接アクセスしても、そうであるように表示されない。たとえば、Object のインスタンスの特異クラスは Object と表示される。また、class() 、type() は特異クラスをスキップして、特異クラスの class() 、type() を返す。したがって、このいずれかのルールにより、通常のクラスのクラスは(クラスの特異クラスのクラスである Class の名をかたった結果か、実際に自らのクラスである Class か、いずれにせよ)単に“Class”と表示する。
特異クラスにアクセスする方法
(Ruby Hacking Guide) クラスとモジュール [日本語] 特異クラスにアクセスする方法がある。def inst_specific_class(obj)
class << obj; self end
end
obj=Object.new
inst_specific_class(obj)==inst_specific_class(obj)
==> true
inst_specific_class(Object.new)==inst_specific_class(Object.new)
==> false
inst_specific_class(Object.new)==Object.new.class
==> false
inst_specific_class(Object)
==> Class # Class の名をかたった Object の特異クラス
inst_specific_class(Object)==inst_specific_class(Object)
==> true
inst_specific_class(Object)==Object.class
==> false
これによると、クラスもやはり class() 、type() で特異クラスを返すのではなく、それをスキップして、そのまたクラスである Class を返している。
つまり戯さんが「シンプルだから、じゃないかな」の余談で言いたかったのはこういうことか。
- 特異クラスは、ひとつめの特異メソッド定義時に作られる無名クラスで、その無名クラスは…
- 特異メソッドの定義先で、
- もとのクラスのサブクラスとして定義され、
- インスタンスのクラスに成り代わるが、
- (しかし class() 、type() は特異クラスをパスするので、あいかわらずものとクラスがクラスだとエンドユーザーは思う)←これは戯さんの発言とは別の sumim の追記
ただ、この“パス”のしかたにはからくりがあって、インスタンスの特異クラスと、クラスの特異クラスで違うらしい。インスタンスの特異クラスでは、本来返すべき特異クラスのスーパークラスが返される。クラスの特異クラスでは、本来返すはずの特異クラスのクラスが返される。実験してみよう。obj.class==inst_specific_class(obj).superclass
==> true
obj.class==inst_specific_class(obj).class
==> false
Integer.class==inst_specific_class(Integer).superclass
==> false
Integer.class==inst_specific_class(Integer).class
==> true
ビンゴ。いやぁ…(Smlaltalk ユーザーからすると)かなり変態的ですね。逆も真でお互い様(Ruby からしたら Smalltalk はかなり偏執的)だろうけど(と、いちおう Ruby ファン向けエクスキューズ)。--sumim
>実体がないということではなく、実体はあるが単にアクセスする手段が用意されていないということか?
>本来返すべき特異クラス
>本来返すはずの特異クラス
特異クラスの役割とか性質を考えると、本来、特異クラスを返すべきではないと思いますが。
例えば、特異クラスが返ってくる事によって、何か大きなメリットとかがあるのでしょうか。
それとは別に、特異クラス「を」返すような(トリッキーでない)関数なりメッセージなりが用意されていれば、いろいろ使い途があるとは思います。--CUE
class というメッセージは本来、レシーバがなんであれ、そのクラスを返すメッセージであるべきという意味で「本来」を使っています。--sumim
特異クラスのインスタンスを作る事って、できるんでしたっけ?
ちょっと手許に確かめる手段がないので、誰か代わりに試してくれる? --CUE
仮想クラスのインスタンスは作れないといったような例外を生じます。1.6.8 (2002-12-24) [arm-linux] + irb --sumim
質問投げてもいいっすか。「メソッドのクラス」という言葉がたびたび出てくるのですが、これは、「メソッドが定義されているクラス」という意味で、同様に「メソッドのスーパークラス」というのは、「メソッドが定義されているクラスのスーパークラス」という意味でよろしいでしょうか?--CUE
すみません、特異クラスを特異メソッドと打ち間違えていました(当該記述、修正しました)。え〜と、この修正で意味は通りますか? お手数でも今一度の読み直しをお願いします。ご指摘、ありがとうございます。--sumim
同様の記述ミスと思われる箇所は他にもあるのですが、勝手に直してみました。strike入れたとこがそうです。--CUE
恐縮です。ご修正いただいた通りです。どうも注意力散漫でいけませんね。お恥ずかしい。ちょっと読みにくかったので勝手ながら当該箇所は削除させていただきました。--sumim
このページを編集 (5519 bytes)
|
以下の 4 ページから参照されています。 |
This page has been visited 5635 times.