在Ruby中覆盖attr_ *方法

时间:2013-01-28 03:15:58

标签: ruby

我正在读这本书“The Well-Grounded Rubyist”,这个随机的问题来找我。我知道在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)

对于上面的两个例子,我希望通过修补并提出问题来更好地理解Ruby。

4 个答案:

答案 0 :(得分: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

test是Ruby中的一个方法,对应于shell中内置的test。这种方法就是你最后收到错误的原因。你真正想要的是

Dummy.attr_accessor(:test1)

请注意,您无法调用普通attr_accessor,因为它是类定义中self类实例的私有方法。 (IOW,attr_accessorModule上的私有实例方法,在执行类定义时,selfModule的实例)

答案 1 :(得分:3)

是的,这是可能的,你刚才做到了!

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

返回nil因为您在下面重新定义它之前使用了attr_accessor :test,因此,Ruby执行了attr_accessor的默认行为并在Dummy类中创建了一个成员和访问者。它返回nil,因为该成员的值未设置... nil

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时出错。

答案 2 :(得分:2)

Dummy班级中调用了Class attr_accessor版本的Dummy,因为attr_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对象上调用方法{{1}}时,您将收到错误,因为没有定义此类方法。

答案 3 :(得分:1)

如果您改变attr_accessor来电和def self.attr_accessor的订单会怎样?我不知道是否会解决这个问题,但你肯定不能按照你的顺序做到这一点。请记住,当您使用类似class Dummy的行打开类时,您将实时执行实际代码。所以首先你正在调用attr_accessor然后你正试图重新定义它。好吧,我不知道你是否可以像这样重新定义它,但你确实需要在之前重新定义它,或者你将调用旧版本!