[ruby-list:50637] Re: instance_evalで定数が見えない
From:
Masahiro Utsumi <utsumi@...>
Date:
2017-12-30 10:29:12 UTC
List:
ruby-list #50637
内海@ベルギーです
instance_eval はインスタンスの挙動を変更するものと考えています。
クラス定義を間違って変えてしまわないように、見る必要のないものは
見えないほうが良いと思います。
class ClassA
CONST="Hello"
@@class_var = "A"
def self.name
@@class_var
end
def hi0
puts "#{CONST} I am #{self.class.name}"
end
end
obj1 = ClassA.new
obj2 = ClassA.new
obj1.instance_eval do
CONST = "Guten tag"
def hi0
puts "#{CONST} I am B"
end
def hi1
puts "Good bye #{self.class.name}"
end
end
obj1.hi0 # Guten tag Ich bin B
obj2.hi0 # Hello I am A
obj1.hi1 # Good bye A
obj2.hi1 # Error
On 2017/12/29 23:44, Akret Node wrote:
> 野口です。
>
> ぼくもこの話は気になるので教えてほしいです。
> クラス変数も同様にレキシカルに決定されると理解しています。
>
> なので、hi1にある@@valはトップレベル(Object?)から探そうとして失敗し、
> 一方でhi3はClassAにある@@valを見つけることができますのでHelloを出力します。
>
> 同じ理屈でいくともとの質問にあるhi1とhi2はどちらも失敗すると思います。
>
> class ClassA
> @@val="Hello"
>
> def self.hi3
> p @@val
> end
> end
>
> class << ClassA
> def hi1
> p @@val
> end
> end
>
> ClassA.instance_eval do
> def hi2
> p @@val
> end
> end
>
> 2017年12月29日 18:48 MASAKI Yuhsuke <yek@reasonset.net>:
>> 内海さん、ありがとうございます。
>>
>> 「あれ、でもinstance_evalでクラス変数にはアクセスできたよね…?」
>> と思ってやってみたところ、できませんでした。
>> なるほど…
>>
>> となると、「instance_eval内でクラスの情報にアクセスしたい」場合の、
>> どうするのが良いでしょうか。
>> アクセサかな?
>>
>>
>> You wrote:
>>> 内海@ベルギーです
>>>
>>> instance_evalはその名前のとおり、インスタンスを evaluate
>>> しているのだと考えています。
>>>
>>> なのでクラス定数を見たければ
>>>
>>> p self.class::CONST
>>>
>>> とすれば見ることができます。
>>>
>>> 定数だけでなくクラス・メソッドになりそうに見えるコード
>>>
>>> def self.hi3
>>> p self.class::CONST
>>> end
>>>
>>> も、instance_eval内ではインスタンスメソッドになりますね。
>>> 一見わかりにくく思えますが、考えればロジカルだと思います。
>>>
>>>
>>> On 2017/12/29 1:51, Yukihiro Matsumoto wrote:
>>>> まつもと ゆきひろです
>>>>
>>>> 定数の参照はレキシカルに決定されますので、instance_evalなど
>>>> では変化しません。
>>>>
>>>>
>>>> In message "Re: [ruby-list:50630] instance_evalで定数が見えない"
>>>> on Fri, 29 Dec 2017 03:24:26 +0900, MASAKI Haruka <yek@reasonset.net> writes:
>>>>>
>>>>> 正木です。
>>>>>
>>>>> Ruby 2.2のときにも言及したのですが、2.5でも変わっていないので再度お聞かせ下さい。
>>>>> インスタンスの特異クラス内では見えるクラスの定数が、instance_evalでは見えません。
>>>>>
>>>>> これは然るべき挙動なのでしょうか。
>>>>>
>>>>> ***
>>>>> コード:
>>>>>
>>>>> class ClassA
>>>>> CONST="Hello"
>>>>> end
>>>>>
>>>>> obj = ClassA.new
>>>>>
>>>>> class <<obj
>>>>> def hi1
>>>>> p CONST
>>>>> end
>>>>> end
>>>>>
>>>>> obj.instance_eval do
>>>>> def hi2
>>>>> p CONST
>>>>> end
>>>>> end
>>>>>
>>>>>
>>>>> 結果:
>>>>>
>>>>> "Hello"
>>>>> Traceback (most resent call last):
>>>>> 1: fron instance_eval_test.rb:20:in `<main>'
>>>>> instance_eval_test.rb:15:in `hi2': uninitialized constant CONST (NameError)
>>>>> ***
>>>>
>>>