Ruby Struct
如果想要存储带属性的数据(key/value或类似key/value的数据),可采用hash或对象来存储,还可以采用struct结构来存储。Ruby中并没有像C、Golang一样提供真正的Struct数据类型,Ruby是以对象的方式实现Struct的,所有Struct结果都是Struct类的子类且内部类。
Struct和对象的区别
如果使用对象的方式存储属性固定且只需存、取方法(也有其它一些基本方法)的数据,一般需要编写如下代码:
1 | class D |
但是可以更简单:
1 | D = Struct.new(:name, :age) |
什么时候使用对象,什么时候使用Struct呢?首先,Struct结构也能当类使用,正如上面的D和普通类没什么区别。如果知道要在小范围内使用,或者是一次性使用的类,那么可以考虑使用Struct。
Struct用法说明
通过Struct.new
可以构造出一个Struct类的子类,这个子类即可当作Struct结构使用,也可当作类来使用。
1 | new([class_name] [, member_name]+) → StructClass |
其中:
因为返回子类,所以可以赋值给一个变量(任意变量名,首字母可小写),此时就有两个名称指向这个类。
1 | p Struct.new("C", :name, :age) # Struct::C |
如果keyword_init
设置为true,则表示创建对象实例时,使用key:value
格式参数。
1 | P = Struct.new(:name, :age, keyword_init: true) |
如果给定语句块,则可以为Struct子类定义实例方法或其它逻辑:
1 | P = Struct.new(:name, :age) do |
建议创建Struct的匿名子类并将其赋值给变量,而不是为其指定一个名称,因为子类都保存在Struct名称空间中,子类名可能会冲突,且匿名子类方便被垃圾回收器回收。
另外,Struct存放的数据的key是固定的,不能随意增加、减少struct成员,因为Struct内部没有定义其它属性的setter/getter方法。
Struct对象的实例方法
Struct对象存取数据很方便,既可以使用对象的点方式,也可以使用数组的数值索引、hash的key索引方式来检索。如果访问不存在的成员或索引越界,则直接报错:
1 | P = Struct.new(:name, :age) |
还有以下几个方法:
1 | each() 迭代所有成员的value |
Struct和Hash结构的区别
- Struct的key是固定不可更改的,无法增、减key,而hash在这方面是自由的
- Struct构建语法更简洁,例如
Foo = Struct.new(:a,:b,:c)
之后,可以不用指定key的名称直接创建struct对象Foo.new(1,2,3)
- 默认情况下,Struct访问不存在的元素会报错,而hash是返回nil,尽管可以设置默认值或fetch()抛错
- Struct对象在遍历时,顺序是固定可保证的
- 可为Struct对象提供能访问成员属性的实例方法,而想要为一部分Hash对象单独提供方法(如果只是单个hash对象,可设置单例方法),稍嫌麻烦
1 | Person = Struct.new(:name, :age) do |