Динамическое определение одноэлементного метода просто при использовании instance_eval
:
Example.instance_eval{ def square(n); n*n; end }
Example.square(2) #=> 4
# you can pass instance_eval a string as well.
Example.instance_eval "def multiply(x,y); x*y; end"
Example.multiply(3,9) #=> 27
Что касается разницы выше, вы путаете 2 вещи:
Определенный вами метакласс - это то, что в сообществе Ruby называется классом сингелтона или собственным классом . Этот одноэлементный класс - это класс, к которому можно добавить методы класса (singleton).
Что касается экземпляра класса, который вы пытаетесь определить с помощью метода class_instance
, это не что иное, как сам класс, чтобы доказать это, просто попробуйте добавить метод экземпляра в класс Example
и проверьте, если class_instance
определенный вами метод возвращает сам класс Example
, проверяя существование этого метода:
class Example
def self.meta; (class << self; self; end); end
def self.class_instance; self; end
def hey; puts hey; end
end
Example.class_instance.instance_methods(false) #=> ['hey']
В любом случае, чтобы суммировать это для вас, когда вы хотите добавить методы класса, просто добавьте их в этот мета класс. Что касается class_instance
метод бесполезен, просто удалите его.
В любом случае, я предлагаю вам прочитать этот пост , чтобы понять некоторые понятия системы отражения Ruby.
UPDATE
Предлагаю вам прочитать этот хороший пост: Приколы с Ruby instance_eval и class_eval ,
К сожалению, class_eval
и instance_eval
сбивают с толку, потому что они как-то работают против их имен!
Use ClassName.instance_eval to define class methods.
Use ClassName.class_eval to define instance methods.
Теперь отвечая на ваши предположения:
Если у меня есть метод экземпляра, который
вызывает self.instance_eval и определяет
метод, это повлияет только на
конкретный экземпляр этого класса.
да
class Foo
def assumption1()
self.instance_eval("def test_assumption_1; puts 'works'; end")
end
end
f1 = Foo.new
f1.assumption1
f1.methods(false) #=> ["test_assumption_1"]
f2 = Foo.new.methods(false) #=> []
Если у меня есть метод экземпляра, который
вызывает self.class.instance_eval (который
будет так же, как звонить
class_eval) и определяет метод это
повлияет на все случаи этого
определенный класс, приводящий к новому
метод экземпляра.
no instance_eval
в этом контексте определит одноэлементные методы (не экземпляры) для самого класса:
class Foo
def assumption2()
self.class.instance_eval("def test_assumption_2; puts 'works'; end")
end
end
f3 = Foo.new
f3.assumption2
f3.methods(false) #=> []
Foo.singleton_methods(false) #=> ["test_assumption_2"]
Для этого замените instance_eval
на class_eval
выше.
Если у меня есть метод класса, который вызывает
instance_eval и определяет метод это
приведет к новому методу экземпляра
для всех случаев.
Нету:
class Foo
instance_eval do
def assumption3()
puts 'works'
end
end
end
Foo.instance_methods(false) #=> []
Foo.singleton_methods(false) #=> ["assumption_3"]
Это создаст одноэлементные методы, а не методы экземпляра. Для этого замените instance_eval
на class_eval
выше.
Если у меня есть метод класса, который вызывает
instance_eval в классе meta / eigen
и определяет метод, который приведет к
метод класса.
ну, нет, это создаст такие сложные вещи, как добавление метода синглтона в класс синглтона, я не думаю, что это будет иметь какое-то практическое применение.