我必须在类my_initialize
中编写一个Class
方法,以便它在这个庄园中工作,当在另一个类中使用时:
class Person
my_initialize :name, :surname
end
相当于:
class Person
def initialize(name, surname)
@name, @surname = name, surname
end
end
如果传递了错误数量的参数,它还必须引发ArgumentError
。例如Person.new("Mickey")
无效。我知道我的代码应该类似于:
class Class
def my_initialize(*args)
args.each do |arg|
self.class_eval("?????")
end
end
end
我刚开始阅读元编程,但找不到对我的问题有用的东西。任何想法如何完成这项任务?
答案 0 :(得分:2)
class Class
def my_initialize(*vars)
define_method :initialize do |*args|
if args.length != vars.length
raise ArgumentError, 'wrong number of arguments'
end
vars.zip(args).each do |var, arg|
instance_variable_set :"@#{var}", arg
end
end
end
end
class C
my_initialize :a, :b
end
Module#define_method
方法接受方法名称和块,并定义该模块的方法。在这种情况下,模块为C
。 Object#instance_variable_set
方法接受实例变量名称和值并设置它。在这种情况下,Object
的实例将是C
的实例。
顺便说一句,最好避免使用传递一串代码进行评估的方法。我建议改为传递块。
答案 1 :(得分:1)
这是另一种不使用define_method
的方式。
class Class
def my_initialize(*vars)
str = "def initialize(*args)
raise ArgumentError if args.size != #{vars.size}
#{vars}.zip(args).each do |var, arg|
instance_variable_set(\"@\#{var}\", arg)
end
end"
class_eval str
end
end
class C
my_initialize :a, :b
end
c = C.new("Betty", "Boop")
#=> #<C:0x00000102805428 @a="Betty", @b="Boop">
C.private_instance_methods(false)
#=> [:initialize]
c.instance_variables
#=> [:@a, :@b]
C.new("Betty")
#=> ArgumentError