Python 类似 Ruby / JRuby 的 __getattr__

发布于 2024-12-18 16:21:10 字数 498 浏览 0 评论 0原文

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

我的用例是: 我正在将 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" ))。

Is there something like Python __getattr__ for Ruby? In Python, obj.__getattr__ is called when an undefined attribute (method or property) is referenced. I found method_missing in Ruby but it doesn't work for properties.

My use case is:
I'm testing Mirah as a JRuby -> Java compiler. In standard JRuby, the Swing methods and attributes are "Rubyfied" (eg: label.setText "x" => label.text = "x"), but not in Mirah, because Mirah doesn't have a propietary runtime library like JRuby. Then, I want to get the attribute references in runtime and map each call to the corresponding Swing method (label.text => label.getText() / label.text = "x" => label.setText("x") ).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

放赐 2024-12-25 16:21:10

我不确定这是否涵盖您的用例,但一般来说, 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     

I'm not sure this covers your use case, but in general, method_missing should do the trick. How would you expect a Ruby class to know the difference between an undefined method and an undefined "property"? All it knows is that it has been passed a name that it does not recognize. Was it supposed to be a method or an property? Who knows? Unless you are talking about setter attributes, in which case, there is a = appended to the name:

 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     
寂寞花火° 2024-12-25 16:21:10

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

有关如何执行此操作的详细信息留给读者作为练习:)

JRuby does this transformation in Java code, by walking the reflected class's methods and adding aliases for the Ruby names. You can do this from Ruby as well. Mirah has access to the actual java.lang.Class instances for all classes you're compiling against, and as a result could do this same name aliasing as part of the compiler phases.

The details on how exactly to do this are left as an exercise for the reader :)

守望孤独 2024-12-25 16:21:10

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_* 方法实际上为您创建方法。

Objects in Ruby do not have "properties". They have instance variables (private variables storing data per instance) and methods that may access these variables.

Because parentheses are optional in Ruby method calls, and because syntax sugar allows you to write obj.foo = 42 as a nicer way of invoking the method obj.foo=( 42 ), you may think that these are properties. They are not; they are methods indistinguishable from any other.

This code:

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

is exactly the same as this (much longer) code:

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

The attr_* methods actually create methods for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文