2

したがって、変数とアクセス メソッドを備えたモジュールが必要です。
私のコードは次のようになります

module Certificates
  module Defaults

  class << self
    attr_accessor :address

    def get_defaults
      address = "something"
      make_root_cert
    end

    def make_root_cert
      blub = address
      # do somthing
    end
  end
end

こじ開けて調べました。
結果は

  • Certificates::Defaults には address と address= というメソッドがあります。
  • get_defaults メソッドでアドレスを呼び出すと、期待どおりに「何か」が返されます
  • make_root_cert で呼び出すと、nil が返されます

この attr_accessor 作成方法を別のモジュールで使用しましたが、うまくいきました。ルビーの仕組みを誤解しているだけで、この例が機能しない理由を誰かが説明できることを願っています。Ruby オブジェクト モデルの実装の詳細を使用している可能性があります。

ジェレミーは正しい。

私の発見

これは私には矛盾しているようです。

  • 式「アドレス」を使用し、インスタンス変数が設定されていない場合、ローカル変数を返します
  • インスタンス変数が設定されていて、ローカル変数が設定されていない場合は、インスタンス変数を返します。
  • 両方が設定されている場合は、ローカル変数を返します。

一方、 address="test"は常にローカル変数を設定します。

4

2 に答える 2

5

get_defaultsメソッドでは、addressローカル変数です。セッターを使用するには、次のように入力する必要があります。

self.address = "something"

これにより、メソッドが適切に呼び出されますaddress=

于 2012-12-19T22:36:52.453 に答える
0

このやや紛らわしい動作は、Ruby インタープリターがメソッド呼び出しよりもローカル変数の定義を優先するために発生します。ここには一貫性がありますが、それがどのように機能するかを事前に知らなければ、明確に理解するのが難しい場合があります.

Ruby の非常に多くのものがオブジェクトとメソッド呼び出しであることを考えると、変数の定義は、何か (カーネル、メイン、またはそれが定義されたオブジェクトなど) で呼び出される何らかのメソッドであると想定するのが自然かもしれません。結果の変数は、ある種のオブジェクトでした。この場合、インタプリタはメソッド検索の規則に従って変数定義と他のメソッドとの間の名前の競合を解決し、同じ名前のメソッドが見つからない場合にのみ新しい変数を定義すると推測できます。最初に潜在的な変数の定義。

ただし、変数定義はメソッド呼び出しではなく、変数はオブジェクトではありません。代わりに、変数はオブジェクトへの単なる参照であり、変数定義はインタープリターが言語の表面の下で追跡するものです。これがシンボルの配列を返す理由Kernel.local_variablesであり、ある種のローカル変数オブジェクトの配列を取得する方法はありません。

そのため、Ruby には、変数とメソッド間の名前の競合を処理するための特別なルール セットが必要です。非ローカル変数には、スコープを示す特別なプレフィックス ($、@ など) があり、これで修正されますが、ローカル変数の場合はそうではありません。もしRubyがメソッドの後に括弧を必要とするなら、それはこの問題にも対処するでしょうが、それをしなくてもよいという贅沢が与えられています。プレフィックスなしでローカル変数を参照し、括弧なしでメソッドを呼び出すという利便性を得るために、言語はデフォルトで、スコープ内にあるときはいつでもローカル変数が必要であると想定します。他の方法で設計することもできましたが、ローカル変数を定義し、プログラムの途中で同じ名前の遠く離れたメソッドによって即座に隠されるという奇妙な状況が発生する可能性があるため、おそらくこのような方が良いでしょう。

Ruby プログラミング言語、p. 88 さんは次のように述べています。

「...ローカル変数には接頭辞として句読点がありません。これは、ローカル変数の参照がメソッド呼び出し式のように見えることを意味します。Ruby インタープリターがローカル変数への代入を見た場合、それが変数であることを認識し、メソッドではなく、変数の値を返すことができます。代入がない場合、Ruby は式をメソッド呼び出しとして扱います。その名前のメソッドが存在しない場合、Ruby はNameError."を発生させます。

nil電話をかけたときになぜ取得していたのかを説明addressmake_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たセッター メソッドは、セッター メソッドが呼び出される前にインタープリターに変数を作成させますが、その変数に 以外の値を割り当てるために呼び出す必要がありますniladdress = "something"inは、呼び出されたメソッド内で、メソッドの最後でスコープ外にget_defaultsなるローカル変数を定義します。addressを呼び出すとmake_root_cert、 と呼ばれるローカル変数がないため、他の値を与えるためにセッター メソッドが呼び出されていないため、取得しaddressたゲッター メソッドが呼び出されて戻ります。新しいローカル変数ではなくクラスメソッドが必要であることをインタープリターに知らせ、あいまいさを解決します。addressattr_accessornilself.address=address=

于 2013-10-22T09:01:11.097 に答える