Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
访问ruby对象中对象的属性_Ruby_Oop_Object Oriented Analysis - Fatal编程技术网

访问ruby对象中对象的属性

访问ruby对象中对象的属性,ruby,oop,object-oriented-analysis,Ruby,Oop,Object Oriented Analysis,我正在构建一个LineItemGenerator对象,其目的是在给定所需属性的情况下生成属性值数组 问题是给定对象将对象作为属性。因此,给定的“属性”实际上是“嵌套属性” 目标是通过创建一些输入数据结构和使用一些算法,从item访问请求的嵌套属性,在本例中是item.name和item.style.name 目前,我将我的“嵌套属性”输入数据结构表示为数组数组,nested\u attributes 我的算法叫做#generate 它采用原始的项和嵌套的_属性。接下来,它映射嵌套的_属性,通过在

我正在构建一个
LineItemGenerator
对象,其目的是在给定所需属性的情况下生成属性值数组

问题是给定对象将对象作为属性。因此,给定的“属性”实际上是“嵌套属性”

目标是通过创建一些输入数据结构和使用一些算法,从
item
访问请求的嵌套属性,在本例中是
item.name
item.style.name

目前,我将我的“嵌套属性”输入数据结构表示为数组数组,
nested\u attributes

我的算法叫做
#generate

它采用原始的
嵌套的_属性
。接下来,它映射
嵌套的_属性
,通过
在每次迭代中将消息发送到原始
,将每个
嵌套的_属性
减少为一个“属性”

class Style
  attr_reader :name
  def initialize name:
    @name = name
  end
end

class Item
  attr_reader :name, :style
  def initialize name:, style:
    @name = name
    @style = style
  end
end

class LineItemGenerator
  def generate item:, nested_attributes:
    nested_attributes.map do |nested_attribute|
      nested_attribute.reduce(item) do |obj, attribute| # <-- algorithm using #reduce to burrow in
        obj.send(attribute)
      end
    end
  end
end


require 'minitest/autorun'

class SomeTest < Minitest::Test
  def test_it_returns_the_right_line_item
    style = Style.new name: 'cool'
    item = Item.new name: 'pants', style: style

    # input data structure is array or arrays
    nested_attributes = [[:name], [:style, :name]]
    input = { item: item, nested_attributes: nested_attributes}
    output = LineItemGenerator.new.generate input
    assert_equal ['pants', 'cool'], output
  end
end

在这种情况下,有没有更好的方法?我的输入数据结构有更好的选择吗?

这对我来说更像是一个软件设计问题,因此我将从设计角度来处理它

  • 每次从一个组件的角度进行推理
  • 将我们试图传达的内容与实施方式分开

LineItemGenerator
的工作是为给定所需属性的项目生成属性值数组

基于此,一个
LineItemGenerator

  • 获取具有属性的项
  • 在给定所需属性列表的情况下,实现
    生成属性值
这可能看起来像:

LineItemGenerator.new(@item).generate_attribute_values(:name, :style)
我要删除
generate
,因为它在这里似乎不是正确的词。我们只是检索和过滤现有值,而不是创建新的属性值对象

LineItemGenerator.new(@item).attribute_values(:name, :style)

在这一点上,我考虑一个<代码>项目<代码>应该暴露给我们的代码> LineItemGenerator < /代码>。

  • 项目具有属性
  • 属性有值,这意味着它们也应该有名称
基于这种理解,我可以将
LineItemGenerator
实现为:

class LineItemGenerator
  def initialize(item)
    @item = item
  end

  def attribute_values(*attribute_names)
    @item.attributes.select { |attribute| attribute_names.include?(attribute.name) }.map(&:value)
  end
end
此时,需要履行两项合同:

  • 项目需要实现
    #属性
  • item.attributes
    需要返回一组响应
    #name
    #value
  • 现在,让我们从一个项目的角度来思考。 -一个项目有许多属性(例如名称和样式)。 -相关属性值可以在
    对象上定义,也可以委托给其他对象

    合同1很难履行:

    class Item
      attr_reader :attributes
    end
    
    契约2更加灵活,因为它可以在条目或单个属性类上实现。如果某个属性不是应用程序中的首要关注点,我会在
    项上实现它

    class Item
      attr_reader :attributes
    
      Attribute = Struct.new(:name, :value)
    
      def initialize(name:, style:)
        @attributes = [
          Attribute.new(name: :name, value: name),
          Attribute.new(name: :style, value: style) 
        ]
      end
    end
    
    如果系统的某些其他部分需要作为一级关注点与属性交互:

    # TODO: DRY up using inheritance or modules
    class Style
      attr_reader :value
      def initialize value:
        @value = value
      end
    
      def name
        :style
      end
    end
    
    class ItemName
      attr_reader :value
      def initialize value:
        @value = value
      end
    
      def name
        :name
      end
    end
    
    class Item
      attr_reader :name, :style, :attributes
      def initialize item_name:, style:
        @name = item_name
        @style = style
    
        @attributes = [@name, @style]
      end
    end
    

    对于一个纯Ruby问题,两个小时后没有答案可能意味着读者不理解它。您实际上是在说,“研究我的代码以理解问题”。这不会产生兴趣。你必须更准确地陈述你的问题。举个例子可能会有很大帮助。如果您给出一个,请确保所有数据都是有效的Ruby对象(例如,no
    [1,2,3…]
    ),为每个输入对象分配一个变量(
    a=[1,2,3]
    ),以便读者可以剪切和粘贴您的代码,并在答案和注释中引用这些变量,而无需定义它们,并显示您想要的结果。这也可能意味着今天是星期六:)。请参阅编辑和包含测试。这有助于澄清问题吗?对于这个问题,您的用例是什么?一个
    行\u项可以有多少类型的对象
    ?为什么一个
    属性数组
    而不是名-值-键值对的散列?@mbigras散列要求
    #属性
    的用户知道这将返回一个原始数据结构,并将解析数据结构的责任交给调用方。
    属性
    对象也更容易扩展(例如添加格式方法等)。事实上,您可以返回
    属性列表
    ,而不是
    数组
    ,数组可能是提取
    属性值
    (例如
    项.属性.值(名称)
    )的更直观的地方。然后,如果应用程序的其余部分不关心
    属性的概念,我们将其委托回
    项.attribute\u值
    ,以完成整个循环
    # TODO: DRY up using inheritance or modules
    class Style
      attr_reader :value
      def initialize value:
        @value = value
      end
    
      def name
        :style
      end
    end
    
    class ItemName
      attr_reader :value
      def initialize value:
        @value = value
      end
    
      def name
        :name
      end
    end
    
    class Item
      attr_reader :name, :style, :attributes
      def initialize item_name:, style:
        @name = item_name
        @style = style
    
        @attributes = [@name, @style]
      end
    end