4

有没有类似 Python __getattr__for Ruby 的东西?在 Python 中,obj.__getattr__当引用未定义的属性(方法或属性)时调用。我method_missing在 Ruby 中找到,但它不适用于属性。

我的用例是:我正在测试Mirah作为 JRuby -> Java 编译器。在标准 JRuby 中,Swing 方法和属性是“Rubyfied”(例如:label.setText "x" => label.text = "x"),但在 Mirah 中不是,因为 Mirah 没有像 JRuby 这样的专有运行时库. 然后,我想在运行时获取属性引用并将每个调用映射到相应的 Swing 方法(label.text => label.getText() / label.text = "x" => label.setText("x") ) .

4

3 回答 3

3

我不确定这是否涵盖了您的用例,但总的来说,method_missing 应该可以解决问题。您希望 Ruby 类如何知道未定义的方法和未定义的“属性”之间的区别?它所知道的只是它被传递了一个它不认识的名字。它应该是一种方法还是一种属性?谁知道?除非您谈论的是 setter 属性,否则在这种情况下,=名称会附加一个:

 class X
   def method_missing name,*args
     puts "missing '#{name}' called with #{args}"
   end
 end  

.

> x = X.new
=> #<X:0xe6b322>
> x.unknown_method
missing 'unknown_method' called with []
=> nil
> x.unknown_property
missing 'unknown_property' called with []
=> nil
> x.unknown_property= 42
missing 'unknown_property=' called with [42]
=> 42     
于 2011-11-28T19:42:58.080 回答
1

JRuby 在 Java 代码中进行这种转换,方法是遍历反射类的方法并为 Ruby 名称添加别名。您也可以从 Ruby 中执行此操作。Mirah 可以访问您正在编译的所有类的实际 java.lang.Class 实例,因此可以在编译器阶段执行相同的名称别名。

关于如何做到这一点的细节留给读者作为练习:)

于 2011-11-28T19:22:06.017 回答
0

Ruby 中的对象没有“属性”。它们有实例变量(每个实例存储数据的私有变量)和可以访问这些变量的方法。

因为括号在 Ruby 方法调用中是可选的,并且因为语法糖允许您编写obj.foo = 42为调用方法的更好方式obj.foo=( 42 ),所以您可能认为这些是属性。他们不是; 它们是与其他任何方法都无法区分的方法。

这段代码:

class Foo
   attr_accessor :bar
end
f = Foo.new
f.bar = 42
puts f.bar  #=> 42

与此(更长)代码完全相同:

class Foo
  def bar
    @bar
  end
  def bar=( val )
    @bar = val
  end
end
f = Foo.new
f.bar=( 42 )
puts( f.bar() ) #=> 42

这些attr_*方法实际上为您创建了方法。

于 2011-11-28T19:58:17.400 回答