このやや紛らわしい動作は、Ruby インタープリターがメソッド呼び出しよりもローカル変数の定義を優先するために発生します。ここには一貫性がありますが、それがどのように機能するかを事前に知らなければ、明確に理解するのが難しい場合があります.
Ruby の非常に多くのものがオブジェクトとメソッド呼び出しであることを考えると、変数の定義は、何か (カーネル、メイン、またはそれが定義されたオブジェクトなど) で呼び出される何らかのメソッドであると想定するのが自然かもしれません。結果の変数は、ある種のオブジェクトでした。この場合、インタプリタはメソッド検索の規則に従って変数定義と他のメソッドとの間の名前の競合を解決し、同じ名前のメソッドが見つからない場合にのみ新しい変数を定義すると推測できます。最初に潜在的な変数の定義。
ただし、変数定義はメソッド呼び出しではなく、変数はオブジェクトではありません。代わりに、変数はオブジェクトへの単なる参照であり、変数定義はインタープリターが言語の表面の下で追跡するものです。これがシンボルの配列を返す理由Kernel.local_variables
であり、ある種のローカル変数オブジェクトの配列を取得する方法はありません。
そのため、Ruby には、変数とメソッド間の名前の競合を処理するための特別なルール セットが必要です。非ローカル変数には、スコープを示す特別なプレフィックス ($、@ など) があり、これで修正されますが、ローカル変数の場合はそうではありません。もしRubyがメソッドの後に括弧を必要とするなら、それはこの問題にも対処するでしょうが、それをしなくてもよいという贅沢が与えられています。プレフィックスなしでローカル変数を参照し、括弧なしでメソッドを呼び出すという利便性を得るために、言語はデフォルトで、スコープ内にあるときはいつでもローカル変数が必要であると想定します。他の方法で設計することもできましたが、ローカル変数を定義し、プログラムの途中で同じ名前の遠く離れたメソッドによって即座に隠されるという奇妙な状況が発生する可能性があるため、おそらくこのような方が良いでしょう。
Ruby プログラミング言語、p. 88 さんは次のように述べています。
「...ローカル変数には接頭辞として句読点がありません。これは、ローカル変数の参照がメソッド呼び出し式のように見えることを意味します。Ruby インタープリターがローカル変数への代入を見た場合、それが変数であることを認識し、メソッドではなく、変数の値を返すことができます。代入がない場合、Ruby は式をメソッド呼び出しとして扱います。その名前のメソッドが存在しない場合、Ruby はNameError
."を発生させます。
nil
電話をかけたときになぜ取得していたのかを説明address
しmake_root_cert
ます。
「そのため、一般的に、初期化される前にローカル変数を使用しようとすると、エラーが発生します。Ruby インタープリターがその変数の代入式を見ると、変数が存在するという奇妙な点が 1 つあります。これは、その代入が実際に実行されない場合. 存在するが値が代入されていない変数にはデフォルト値が与えられますnil
. 例:
a = 0.0 if false # This assignment is never executed
print a # Prints nil: the variable exists but is not assigned
print b # NameError: no variable or method named b exists"
取得しattr_accessor
たセッター メソッドは、セッター メソッドが呼び出される前にインタープリターに変数を作成させますが、その変数に 以外の値を割り当てるために呼び出す必要がありますnil
。address = "something"
inは、呼び出されたメソッド内で、メソッドの最後でスコープ外にget_defaults
なるローカル変数を定義します。address
を呼び出すとmake_root_cert
、 と呼ばれるローカル変数がないため、他の値を与えるためにセッター メソッドが呼び出されていないため、取得しaddress
たゲッター メソッドが呼び出されて戻ります。新しいローカル変数ではなくクラスメソッドが必要であることをインタープリターに知らせ、あいまいさを解決します。address
attr_accessor
nil
self.address=
address=