Ruby ruby method_missing 重写报错, 望大牛给予帮助

wukong · 2013年04月09日 · 最后由 chenge 回复于 2016年07月04日 · 3481 次阅读
class MyOpenStruct < BasicObject
    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
            _singleton_class.instance_exec(name) do |name|
                define_method(name) do |value|
                    @values[base_name] = value
                end
            end
            @value[base_name] = args[0]
        else
            #super unless @values.has_key? name
            _singleton_class.instance_exec(name) do |name|
                define_method(name) do
                    @values[name]
                end
            end
            @values[name]
        end
    end
end
my = MyOpenStruct.new(name: "chenchao")
my.address = "beijing"
my.likes = "beauty girl"
puts "#{my.name} lives in #{my.address} , likes #{my.likes}"

执行收到错误信息是 /home/stephan/work/test/hook.rb:61:in method_missing': undefined method[]=' for nil:NilClass (NoMethodError) from /home/stephan/work/test/hook.rb:74:in `' 检查程序没发现错误,求指教

不排版是故意设置的门槛吗...哇哈哈哈哈 好像有很多拼写错误啊 比如 base_name 一下就成了 basename, @values的循环外面也有@value? 还有singleton_class 前面那个?改了应该就没问题了吧

@values[base_name] = args[0], 这一行写错了。

这个代码还是有点复杂的,不知道是原创还是来自何处。

这种排版我基本上不会看。

class MyOpenStruct
    def initialize(initial_values = {})
        @values = initial_values
    end
    def method_missing(name, *args, &block)
        if name[-1] == "="
            base_name = name[0..-2].intern
            @values[base_name] = args[0]
        else
            @values[name]
        end
    end
end
my = MyOpenStruct.new(name: "chenchao")
my.address = "beijing"
my.likes = "beauty girl"
puts "#{my.name} lives in #{my.address} , likes #{my.likes}"

似乎可以删除部分代码。

对了,missing 内不能用 puts 打印参数我要看参数怎么能实现?大神,求指教

#5 楼 @wukong 不要用 BasicObject。

怎么解?小弟,学艺不精望指教,

#5 楼 @wukong 直接用 ::Kernel.puts 也可以

def method_missing(name, *args, &block)
   ::Kernel.puts name
    ...
end

@skandhas 谢谢你的方法,刚用了真好用!

#1 楼@krazy 谢谢你的指教,可以了

@chenge 这个程序不是原创,只是在学习 ruby 元编程时找的 demo

@chenge 还有就是为什莫不要用 BasicObject,小弟学艺不精望指教

#12 楼 @wukong 你看我改写的代码。Object 默认带 Kernel,BasicObject 不带 Kernel。

建议重新排版并且将标题中的错别字改正,效果会更好

@chenge 那意思是不带 kernel 会不会运行效率高一点呢?

@donnior 嗯,好的。没问题我再重新排一下版。你的意见很不错,

#15 楼 @wukong 效率几乎可以忽略不计。

@donnior 哥们儿,已经修改了,

chenge Ruby 学习汇集,请推荐内容 提及了此话题。 07月04日 11:35
需要 登录 后方可回复, 如果你还没有账号请 注册新账号