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

以元编程方式定义采用关键字参数的Ruby方法?

发布时间:2020-12-17 04:39:36 所属栏目:百科 来源:网络整理
导读:Struct允许我创建一个新的类,它接受参数并具有一些很好的语义.但是,参数不是必需的,它们的顺序需要参考定义: Point = Struct.new(:x,:y)Point.new(111,222)#= point instance with x = 111,y = 222Point.new(111)#= point instance with x = 111,y = nil 我
Struct允许我创建一个新的类,它接受参数并具有一些很好的语义.但是,参数不是必需的,它们的顺序需要参考定义:
Point = Struct.new(:x,:y)

Point.new(111,222)
#=> <point instance with x = 111,y = 222>

Point.new(111)
#=> <point instance with x = 111,y = nil>

我想要类似于Struct的东西,但它使用关键字参数代替:

Point = StricterStruct.new(:x,:y)

Point.new(x: 111,y: 222)
#=> <point instance with x = 111,y = 222>

Point.new(x: 111)
#=> ArgumentError

这可能看起来像这样:

module StricterStruct
  def self.new(*attributes)
    klass = Class.new
    klass.instance_eval { ... }

    klass
  end
end

但是在大括号中应该怎么做才能在klass上定义一个初始化方法:

>它需要没有默认值的关键字参数;
>关键字作为属性中的符号数组给出;和
> initialize方法将它们分配给同名的实例变量

解决方法

由于Ruby 2.0中的新功能,我使用(令人惊讶的Pythonic)** kwargs策略结束了:
module StricterStruct
  def self.new(*attribute_names_as_symbols)
    c = Class.new
    l = attribute_names_as_symbols

    c.instance_eval {
      define_method(:initialize) do |**kwargs|
        unless kwargs.keys.sort == l.sort
          extra   = kwargs.keys - l
          missing = l - kwargs.keys

          raise ArgumentError.new <<-MESSAGE
            keys do not match expected list:
              -- missing keys: #{missing}
              -- extra keys:   #{extra}
          MESSAGE
        end

        kwargs.map do |k,v|
          instance_variable_set "@#{k}",v
        end
      end

      l.each do |sym|
        attr_reader sym
      end
    }

    c
  end
end

(编辑:李大同)

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

    推荐文章
      热点阅读