Ответ 1
Определение метода singleton динамически просто, когда вы используете 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 как класс singelton или собственный класс. Этот одноэлементный класс - это класс, к которому вы можете добавить методы класса (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
Я предлагаю вам прочитать этот хороший пост: Fun с 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"]
Это сделает методы singleton, а не методы экземпляра. Для этого замените instance_eval
на class_eval
выше.
Если у меня есть метод класса, который вызывает instance_eval в мета/собственном классе и определяет метод, который приведет к метод класса.
ну нет, это сделает такой сложный материал, поскольку он добавит метод singleton к классу singleton, я не думаю, что это будет иметь практическое применение.