Ruby有未定义的实例变量的method_missing等价物吗?
当我调用一个不存在的方法时, method_missing
会告诉我该方法的名称。 当我尝试访问尚未设置的变量时,该值只是nil
。
我试图动态拦截对nil实例变量的访问,并根据被访问变量的名称返回一个值。 最接近的等价物是PHP的__get
。 Ruby中有没有相同的function?
我不相信这在Ruby中是可行的。 推荐的方法是在模板中使用“用户”方法而不是“@user”实例var。
这与外部处理Ruby对象的方式一致(”obj.user”是一个引用”@user”的方法,但实际上并不是”@user”本身)。 如果您需要具有属性的任何特殊逻辑,最好的方法是使用方法(或method_missing),无论您是从对象内部还是外部访问它。
看看我对另一个类似问题的回答 。 但仅仅因为你能做到并不意味着这是一个好主意。 明智的设计通常可以克服对此类事物的需求,并允许您生成更易读且可维护的代码。
instance_variable_get
似乎是我所能看到的最接近PHP的__get
(尽管我不是PHP用户)。
查看相关的Ruby源代码 ,变量的唯一“缺失”方法是常量的const_missing
,实例变量没有。
没有instance_variable_missing(至少我知道)但是为什么你要访问随机命名的实例变量呢?
如果你的线程通过方法调用对所有对象的访问状态(你应该如此),那么你就不需要这样了。
如果您正在寻找一种方法来定义魔术,而不会弄乱方法查找,您可能需要使用const_missing
。
有点晚了但是, instance_variable_missing
与method_missing
到一个点相同……采取以下类:
class Test def method_missing(*args) puts args.inspect end end t = Test.new
现在让我们来看一些实例变量:
t.pineapples #=> [:pineapples] t.pineapples = 5 #=> [:pineapples=,5]
不知道为什么这个方法对你来说是零的…
编辑:
通过你想要完成的声音:
t = SomeClass.new t.property.child = 1
所以让我们尝试从前面的示例返回一个Test
对象:
class Test def method_missing(*args) puts args.inspect return Test.new end end
那么当我们打电话时会发生什么
t = Test.new t.property.child = 1 #=>[:property] #=>[:child=,1]
所以这表明这确实是可行的。 OpenStruct
使用相同的技术动态设置实例变量。 在下面的示例中,我创建了EternalStruct
,它完全符合您的要求:
require 'ostruct' class EternalStruct < OpenStruct def method_missing(*args) ret = super(*args) if !ret newES = EternalStruct.new self.__send__((args[0].to_s + "=").to_sym, newES) return newES end end end
EternalStruct
用法:
t = EternalStruct.new t.foo.bar.baz = "Store me!" t.foo.bar.baz #=> "Store me!" t.foo #=> #> ta = 1 ta #=> 1 tb #=> # tb = {} tb #=> {} def tc(arg) puts arg end tc("hi there") #=> "hi there"