Python как __getattr__ для Ruby / JRuby
Есть ли что-то вроде Python __getattr__
для Руби? В 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")),
3 ответа
Я не уверен, что это относится к вашему случаю использования, но в общем случае method_missing должен сработать. Как вы ожидаете, что класс Ruby узнает разницу между неопределенным методом и неопределенным "свойством"? Все, что он знает, - это то, что ему было присвоено имя, которое он не распознает. Это должен был быть метод или свойство? Кто знает? Если вы не говорите об атрибутах сеттера, в этом случае есть =
добавляется к имени:
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
JRuby выполняет это преобразование в коде Java, обходя методы отраженного класса и добавляя псевдонимы для имен Ruby. Вы можете сделать это и из Ruby. Mirah имеет доступ к фактическим экземплярам java.lang.Class для всех классов, с которыми вы компилируете, и в результате может делать это имя с псевдонимами как часть фаз компиляции.
Подробности о том, как именно это сделать, оставлены в качестве упражнения для читателя:)
Объекты в 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_*
методы на самом деле создают методы для вас.