[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)
>>>>> ***
>>>>
>>>

In This Thread

Prev Next