Ruby中的OpenStruct和Struct

OpenStruct

如官方文档介绍, OpenStruct是一个类似Hash的数据结构,它允许我们使用对象自带的值定义任意的属性,
这是通过使用Ruby的元编程来定义类本身的方法来实现的.
说白了就是通过一个数据结构来模拟class,有些数据有自己的属性,但是使用class会比较复杂,使用hash即可满足,但是hash存取值又不太方便,这是OpenStruct就排上用场了。

require 'ostruct'
post = OpenStruct.new(title: "My first post", content: "My first post content")
# 三种读取方式返回相同的值
post.title    #=>  "My first post"
post[:title]  #=> "My first post"
post['title']  #=> "My first post"

OpenStruct类也包含很多类方法:
to_h可以方便的转化为hash, 如:
post.to_h #=> {:title=>"My first post", :content=>"My first post content"}
delete_field可以删除某个元素:

post.delete_field(:content)  #=>  {:title=>"My first post"}

虽然在Ruby中OpenStruct封装的很好用,但是有性能性能,具体参考:https://stackoverflow.com/questions/1177594/when-should-i-use-struct-vs-openstruct#answer-4459132

Struct

Struct本质上是一个简单的类,它允许你在不用定义class的情况下封装属性和accessor方法。

创建一个Struct:

Post = Struct.new(:title, :content)
post = Post.new('my title', 'my content')
# 三种读取方式返回相同的值:
post.title    #=>  "My first post"
post[:title]  #=> "My first post"
post['title']  #=> "My first post"

Struct的方法:

post.values  #=> ["my title", "my content"]
post.to_h  #=> {:title=>"my title", :content=>"my content"}

Struct比OpenStruct更优的地方是在Struct内部可以定义方法:

Post = Struct.new(:title, :content) do
   def display_title
      title.to_s + " created at today"
   end
end
Post.new("my title", "my content").display_title  #=> "my title created at today"

什么时候使用Struct?

Struct像是一个简单的封装了属性和方法的类.

那么Struct的适用场景是什么呢

使用Struct最大的好处是它可以比hash或者array更好的表明数据的意义.

比如,假设你有下面记录坐标数据的数组:

locations = [[40.748817, -73.985428], [40.702565, 73.992537]]

这个数组看起来并不能很清楚的展示其中的值是代表的坐标相关的数据。

现在我们使用Struct来定义这些值:

Location = Struct.new(:longitude, :latitude)
location = Location.new(40.748817, -73.985428)
location.longitude   #=> 40.748817

当要处理的是相关性比较强的数据时,你应该使用用Struct.比如上面的location的属性关联密切, 所以比较适合封装成一个对象.

使用Struct的类比Hash还有一个好处是Struct值require指定的属性,而Hash可以接受任何值.

比如,假设我们正在处理一些关于book的结构化的数据,如果我们使用Hash:

book = {}
book[:tile] = 'Jane Eyre'

这个Hash不管我们拼写的title是否正确,都会加到Hash中.

而使用Struct不会出现这个问题.

同样取坐标的例子:

Location = Struct.new(:longitude, :latitude)
location = Location.new(40.748817, -73.985428)
location.longitud   #=> undefined method `longitud' for struct

参考:http://culttt.com/2015/04/15/working-with-structs-in-ruby/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,347评论 19 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,254评论 25 709
  • hello,word
    黄渤阅读 1,456评论 0 0
  • 生活总是让我们遍体鳞伤,但到后来,那些受伤的地方一定会变成我们最强壮的地方。 ——海明威 01 我曾常常向朋友讲述...
    温姬拉阅读 3,480评论 3 3
  • 版本号【2.1】版本号 更新信息【本软件需要更新,软件多加个性感图片和新的VIPS 视频,本软件还会更新的东西,喜...
    天哥作者阅读 2,415评论 0 1