加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 从模块创建类方法

发布时间:2020-12-17 02:37:05 所属栏目:百科 来源:网络整理
导读:给出一个简单的例子: class Base @tag = nil def self.tag(v = nil) return @tag unless v @tag = v end end class A Base tag :Aendclass B Base tag :Bend class C Base; endputs "A: #{A.tag}"puts "B: #{B.tag}"puts "A: #{A.tag}"puts "C: #{C.tag}"
给出一个简单的例子:

class Base
  @tag = nil 

  def self.tag(v = nil) 
    return @tag unless v 
    @tag = v
  end 
end 

class A < Base 
  tag :A
end

class B < Base
  tag :B
end 

class C < Base; end

puts "A: #{A.tag}"
puts "B: #{B.tag}"
puts "A: #{A.tag}"
puts "C: #{C.tag}"

它按预期工作

A: A
B: B 
A: A
C:

我想创建一个模块,该模块将扩展为提供相同的功能,但具有该类指定的所有标记信息.例如.

module Tester 
  def add_ident(v); ....; end
end

class Base 
  extend Tester 

  add_ident :tag
end

我发现我可以直接使用它,所以:

def add_ident(v)
  v = v.to_s 
  eval "def self.#{v}(t = nil); return @#{v} unless t; @#{v} = t; end"
end

但我真的不喜欢在任何语言中使用eval字符串.

有没有办法可以在不使用eval的情况下获得此功能?我已经完成了我能想到的define_method和instance_variable_get / set的每个组合,我无法让它工作.

没有Rails的Ruby 1.9.

解决方法

您希望在要扩展的类的单例类上定义动态方法.可以使用如下表达式访问类的单例类:class<<自;自我结束.要打开类的范围,可以使用class_eval.把所有这些放在一起,你可以写:

module Identification

  def add_identifier(identifier)
    (class << self; self end).class_eval do
      define_method(identifier) do |*args|
        value = args.first
        if value
          instance_variable_set("@#{identifier}",value)
        else
          instance_variable_get("@#{identifier}")
        end
      end
    end
  end

end

class A
  extend Identification

  add_identifier :tag
end

如果您使用的是最新版本的Ruby,则可以使用Module#define_singleton_method替换此方法:

module Identification

  def add_identifier(identifier)
    define_singleton_method(identifier) do |value = nil|
      if value
        instance_variable_set("@#{identifier}",value)
      else
        instance_variable_get("@#{identifier}")
      end
    end
  end

end

我不相信你想使用self.class.send(:define_method),如另一个答案所示;这有一个意外的副作用,即将动态方法添加到self.class的所有子类中,在我的示例中,A的情况是Class.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读