3

私はこの本「TheWell-GroundedRubyist 」を読んでいて、このランダムな質問が私に来ました。Rubyでは、クラスを再度開いてメソッドを上書きできることを知っています。

例:

class A
  def x
    "First definition of x"
  end

  def x
    "Second definition of x"
  end
end

test = A.new
test.x #returns "Second definition of x"

上記の結果に基づいて、クラスメソッドattr_accessorを自分の(ランダムな)定義で上書きできるかどうか興味がありました。これが私が考えていることです:

class Dummy
  attr_accessor :test

  def self.attr_accessor(method_name)
    puts "Overwrite the default functionality of attr_accessor by printing this text instead."
  end
end

d = Dummy.new
d.test #not sure why this returns nil instead of putting my message
Dummy.attr_accessor(test) #fails because of ArgumentError: wrong number of arguments (0 for 2..3)

上記の2つの例では、Rubyをいじくり回して質問し、洞察を得ることで、Rubyをよりよく理解したいと思っています。

4

4 に答える 4

6

あなたは正しい道を進んでいますが、クラス定義は実行時に順番に実行されます。新しいメソッドを呼び出す前に定義する必要があります。そうしないと、元のメソッドがそのメソッドに使用されます。

もし、するなら

class Dummy
  def self.attr_accessor(method)
    puts 'your message here'
  end
  attr_accessor :test # message printed
end

d = Dummy.new
d.test # raises an error, since we aren't creating a test method anymore
Dummy.attr_accessor(test) #will still fail, read on

testtest組み込みのシェルに対応するRubyのメソッドです。その方法が、最後にエラーが発生する理由です。あなたが実際に望んでいるのは

Dummy.attr_accessor(:test1)

通常のを呼び出すことはできないことに注意してください。これは、クラス定義内にattr_accessorあるクラスインスタンスのプライベートメソッドであるためです。self(IOWattr_accessorは、のプライベートインスタンスメソッドでModuleあり、クラス定義を実行するときselfは、のインスタンスですModule

于 2013-01-28T03:26:34.143 に答える
3

はい、それは可能です、そしてあなたはそれをやっただけです!

d.test #not sure why this returns nil instead of putting my message

以下で再定義する前にnil使用したため、Rubyはのデフォルトの動作を実行し、クラスにメンバーとアクセサーを作成しました。メンバーの値が設定されていないために返されます。attr_accessor :testattr_accessorDummynilnil

Dummy.attr_accessor(test) #fails because of ArgumentError: wrong number of arguments (0 for 2..3)

あなたが考える理由ではなく失敗します。この呼び出しは機能します:

Dummy.attr_accessor("method_name") 

問題は、という名前のメソッドを呼び出してtestいて、その期待値のすべてを提供していないことです。Kernel.test() http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-testのドキュメントを参照してください。

表示されるエラーメッセージは、テストメソッドを誤って呼び出しているためであり、の再定義の誤りが原因ではありませんattr_accessor

于 2013-01-28T03:35:33.983 に答える
2

Dummyクラスでは、が呼び出された時点でバージョンがまだ定義されていないため、のClassバージョンが呼び出されます。呼び出しの前に定義を移動すると、動作が異なります。attr_accessorDummyattr_accessor

class Dummy    
  def self.attr_accessor(method_name)
    puts "Overwrite the default functionality of attr_accessor by printing this text instead."
  end

  attr_accessor :test
end

これにより、クラス定義が読み取られたときにメッセージが出力されます。testオブジェクトでメソッドを呼び出そうとすると、Dummyそのようなメソッドが定義されていないため、エラーが発生します。

于 2013-01-28T03:26:23.283 に答える
1

通話と通話の順序を逆にするとどうattr_accessorなりますdef self.attr_accessorか?それがそれを修正するかどうかはわかりませんが、あなたは確かにあなたの注文でそれを行うことはできません。のような行でクラスを開くと、class Dummy実際のコードをリアルタイムで実行していることを忘れないでください。つまり、最初に電話をかけattr_accessor次にそれを再定義しようとしています。そうですね、そのように再定義できるかどうかはわかりませんが、呼び出すに再定義する必要があります。そうしないと、古いバージョンを呼び出すことになります。

于 2013-01-28T03:26:02.523 に答える