通过Struct一般用于创建具有结构化数据的类,一般方式如下
#通过Struct.new创建Customer类
#通过在块中创建方法来创建Customer类的实例方法
#对Struct.new中的属性实现了attr_accessor方法
Customer = Struct.new(:name, :address) do
def greeting
"Hello #{name}!"
end
end
dave = Customer.new("Dave", "123 Main")
dave.name #=> "Dave"
dave.greeting #=> "Hello Dave!"
dave.name = "jayzen"
dava.name #"jayzen"
#对比Class类方式创建类
Customer = Class.new do
def greeting
"hello world"
end
end
obj = Customer.new.greeting #"hello world"
通过Struct来创建类的第二种方式
#Struct.new的第一个参数是需要创建的类本身,通过Struct::类来记性类的实例化操作
Struct.new("Customer", :name, :address)
Struct::Customer.new("Dave", "123 Main")
Tip:将Struct.new的返回值赋值给常量,并像类一样使用它
代码示例中,通过hash来存储数据,对比hash和struct
require 'csv'
class Demo
def initialize(file_name)
@readings = []
CSV.foreach(file_name, headers: true) do |row|
@readings << {
high: row[3],
low: row[2]
}
end
end
def mean
return 0.0 if @readings.size.zero?
total = @readings.reduce(0.0) do |sum, reading|
sum + (reading[:high].to_f + reading[:low].to_f)/2.0
end
total.to_f / @readings.size.to_f
end
end
obj = Demo.new("/Users/jayzen/Desktop/csvs.csv")
p obj.mean
上面代码的问题罗列如下
1.在mean方法中,如果要访问hash里面的数据,需要了解hash内部的细节(即哪个键对应哪个值),因此对initiailze方法内容有详细的了解。
2.hash如果是按照hash['name']的形式来进行数据访问,这样缺少访问限制。
下面的方法通过使用Struct类来进行改进。
require 'csv'
class Demo
Reading = Struct.new(:high, :low)
def initialize(file_name)
@readings = []
CSV.foreach(file_name, headers: true) do |row|
@readings << Reading.new(row[3], row[2])
end
end
def mean
return 0.0 if @readings.size.zero?
total = @readings.reduce(0.0) do |sum, reading|
sum + (reading.high.to_f + reading.low.to_f)/2.0
end
total.to_f / @readings.size.to_f
end
end
obj = Demo.new("/Users/jayzen/Desktop/csvs.csv")
p obj.mean
通过reading.high的形式更符合面向对象语言的使用习惯。
下面利用Struct中生成方法的方式来更新mean方法。
require 'csv'
class Demo
Reading = Struct.new(:high, :low) do
def mean
(high.to_f + low.to_f) / 2.0
end
end
def initialize(file_name)
@readings = []
CSV.foreach(file_name, headers: true) do |row|
@readings << Reading.new(row[3], row[2])
end
end
def mean_value
total = @readings.reduce(0.0) do |sum, reading|
sum + reading.mean
end
total / @readings.size.to_f
end
end
obj = Demo.new("/Users/jayzen/Desktop/csvs.csv")
p obj.mean_value