Ruby中缺少方法和定义方法
有以下代码:Ruby中缺少方法和定义方法,ruby,Ruby,有以下代码: class MyOpenStruct def initialize(initial_values = {}) @values = initial_values end def _singleton_class class << self self end end def method_missing(name, *args, &block)
class MyOpenStruct
def initialize(initial_values = {})
@values = initial_values
end
def _singleton_class
class << self
self
end
end
def method_missing(name, *args, &block)
if name[-1] == "="
base_name = name[0..-2].intern
puts "add_method_to_set"
self.class.add_method_to_set(base_name)
@values[base_name] = args[0]
else
puts "add_method_to_get"
self.class.add_method_to_get(base_name)
@values[name]
end
end
def self.add_method_to_get(name)
define_method(name) do |value|
@values[name]
end
end
def self.add_method_to_set(name)
define_method(name) do |value|
@values[name] = value
end
end
end
obj1 = MyOpenStruct.new(name: "Dave")
obj1.address = "1"
obj2 = MyOpenStruct.new(name: "Dave")
obj2.address = "2"
类MyOpenStruct
def初始化(初始值={})
@值=初始值
结束
def(单例)类
类@koffeinfrei发现了代码中的一个问题,但我发现了其他一些问题。下面是我认为正确的版本。我还提出了另一种构建代码的方法。我的主要建议是退出实例方法的动态创建,因为这是非常通用的。您甚至可以根据需要将其与其他方法一起放入模块中
您的代码及其修复
class MyOpenStruct
def initialize(initial_values = {})
@values = initial_values
end
def method_missing(name, *args, &block)
puts "in mm, name = #{name}"
if name[-1] == "="
base_name = name[/\w+/]
puts "add_method_to_set: '#{name}'"
self.class.add_method_to_set(base_name)
@values[base_name.to_sym] = args[0]
else
puts "add_method_to_get: '#{name}'"
self.class.add_method_to_get(name)
@values[name.to_sym]
end
end
def self.add_method_to_get(name)
define_method(name.to_sym) do
@values[name.to_sym]
end
end
def self.add_method_to_set(name)
define_method((name+'=').to_sym) do |value|
@values[name.to_sym] = value
end
end
end
备选结构
def create_instance_eval(klass, method, &block)
klass.class_eval { define_method(method, &block) }
end
class MyOpenStruct
def initialize(initial_values = {})
@values = initial_values
end
def method_missing(name, *args, &block)
if name[-1] == "="
base_name = name[/\w+/]
method_name = (base_name+'=').to_sym
puts "create method '#{method_name}'"
method = create_instance_eval(self.class, method_name) do |value|
@values[base_name.to_sym] = value
end
send(method, args[0])
else
method_name = name.to_sym
puts "create method '#{method_name}'"
method = create_instance_eval(self.class, method_name) do
@values[method_name]
end
send(method)
end
end
end
示例
MyOpenStruct.instance_methods(false)
#=> [:method_missing]
obj1 = MyOpenStruct.new(name: "Dave")
#=> #<MyOpenStruct:0x00000102805b58 @values={:name=>"Dave"}>
obj1.address = "1"
# create method 'address='
#=> "1"
MyOpenStruct.instance_methods(false)
#=> [:method_missing, :address=]
obj2 = MyOpenStruct.new(name: "Mitzy")
#=> #<MyOpenStruct:0x00000101848878 @values={:name=>"Mitzy"}>
obj2.address = 2
#=> 2
obj2.address
# create method 'address'
# => 2
MyOpenStruct.instance_methods(false)
$#=> [:method_missing, :address=, :address]
obj1.instance_variable_get(:@values)
#=> {:name=>"Dave", :address=>"1"}
obj2.instance_variable_get(:@values)
#=> {:name=>"Mitzy", :address=>2}
MyOpenStruct.instance_方法(false)
#=>[:方法_缺失]
obj1=MyOpenStruct.new(名称:“Dave”)
#=>#“Dave”}>
obj1.address=“1”
#创建方法“address=”
#=> "1"
MyOpenStruct.instance_方法(false)
#=>[:方法_缺失,:地址=]
obj2=MyOpenStruct.new(名称:“Mitzy”)
#=>#“米兹”}>
obj2.address=2
#=> 2
obj2.address
#创建方法“地址”
# => 2
MyOpenStruct.instance_方法(false)
$#=>[:方法_缺失,:地址=,:地址]
obj1.instance_variable_get(:@values)
#=>{:name=>“Dave”,:address=>“1”}
obj2.instance_variable_get(:@values)
#=>{:name=>“Mitzy”,:address=>2}
setter方法的方法名称需要有trailing=,因此您需要使用名称来定义方法,而不是基本名称
self.class.add_method_to_set(name)
使用一些默认值为初始集播种不是更好吗,比如调用super({address:'}.merge(initial_values))
内部的initialize
?如果您需要该功能,我在确定后就这样做了。提示:检查您定义的方法的名称