【问题标题】:What's the purpose of an anonymous struct in Ruby?Ruby 中匿名结构的目的是什么?
【发布时间】:2012-01-26 01:13:47
【问题描述】:

可以这样定义

Struct.new(:x, :y)

但是可以用它们做什么有用的事情呢?具体来说,如何创建这种结构的实例?这不起作用

Struct.new(:x => 1, :y => 1)

(你会得到TypeError: can't convert Hash into String)。

我使用的是 Ruby 1.9.2。

更新:

到目前为止的建议很好,谢谢。我想我问这个的原因是我有好几次发现自己想要这样做

Struct.new(:x => 1, :y => 1)

只是为了让我可以传递一个可以写obj.x 的对象,而不是例如实例化一个哈希并不得不写obj[:x]。在这种情况下,我希望结构是真正匿名的——我不想通过命名Struct.new 调用返回的内容来污染我的命名空间。正如已经建议的那样,最接近的事情是

Struct.new(:x, :y).new(1, 1)

但是你喜欢他们的苹果吗?我不确定我知道。期望能够一次性定义和实例化匿名结构(作为核心 Ruby 的一部分)是否合理?我想当我阅读Struct.new 上的官方 Ruby 文档时,我认为“匿名”这个词允许这样做,但事实并非如此。

【问题讨论】:

标签: ruby


【解决方案1】:

OpenStruct 可能是您想要的,但我最近遇到了OpenStruct 不起作用的情况,因为我在尝试访问未定义的属性时需要引发错误。 Struct 这样做

os = OpenStruct.new
os.x = 1; os.y = 2;
os.z # returns nil

s = Struct.new(:x, :y).new
s.x = 1; s.y = 2;
s.z # raises NoMethodError

只是需要记住的一点。

【讨论】:

    【解决方案2】:

    好吧,当您实际上不想编写带有访问器的类时,您可以使用 Structs。写起来很方便

    Project = Struct.new(:name)
    

    而不是

    class Project
      attr_accesor :name
    end
    

    正如 tokland 正确指出的那样(谢谢!),Struct 还自动为您提供了一个不错的 #initialize 方法。因此,无需任何其他代码即可实现以下操作:

    Project = Struct.new(:name)
    p = Project.new('Quadriloptic Curves')
    

    【讨论】:

    • 使用 Struct 还可以获得一个初始化程序。 (类型 -> 访问者 -> 访问者)
    【解决方案3】:

    Struct.new 返回一个Class,因此您可以将它分配给一个常量,例如:

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

    或子类化它:

    class Point < Struct.new(:x, :y)
      # custom methods here
      # ...
    end
    

    在这两种情况下,您都可以像这样使用生成的类:

    Point.new(3, 5)
    

    如果您不想创建特定类(因为您只需要实例化该类的对象一次),请考虑改用OpenStruct

    require 'ostruct'
    
    point = OpenStruct.new(:x => 3, :y => 5)
    

    【讨论】:

    • +1 我读过的第一个解释听起来确实有点用。
    • 就像OpenStruct 的建议一样——这最符合我对Struct.new 的预期。
    【解决方案4】:

    关于创建实例:

    User = Struct.new(:user,:password)
    u = User.new("john","secret")
    

    【讨论】:

      【解决方案5】:

      您首先创建一个结构,然后您可以创建它的实例。这是一种无需声明类即可创建数据对象的方法。基本上它与哈希相同,但访问对象更干净。您可以通过普通访问器方法引用它来从中获取内容。

      http://www.ruby-doc.org/core-1.9.3/Struct.html

      # Create a structure with a name in Struct
      Struct.new("Customer", :name, :address)    #=> Struct::Customer
      Struct::Customer.new("Dave", "123 Main")   #=> #<struct Struct::Customer name="Dave", address="123 Main">
      
      # Create a structure named by its constant
      Customer = Struct.new(:name, :address)     #=> Customer
      Customer.new("Dave", "123 Main")           #=> #<struct Customer name="Dave", address="123 Main">
      

      【讨论】:

        【解决方案6】:

        我很确定目的,但 Struct.new 返回类所以

        irb(main):001:0> Struct.new(:x,:y)
        => #<Class:0x2914110>
        irb(main):002:0> Struct.new(:x,:y).new(1,2)
        => #<struct x=1, y=2>
        

        【讨论】:

        • 是的,第二行是漂亮还是丑陋,我无法决定!
        • 对我来说似乎更丑而不是美丽。我想这违反了德米特法则。我对 s Struct 的用法不是很熟悉。
        猜你喜欢
        • 1970-01-01
        • 2015-02-23
        • 2019-09-28
        • 1970-01-01
        • 2010-10-04
        • 1970-01-01
        • 1970-01-01
        • 2023-03-04
        • 1970-01-01
        相关资源
        最近更新 更多