轨道
/
Crystal
Crystal
/
练习
/
称重机
称重机

称重机

学习练习

简介

getter 和 setter 是方法,让你可以读取和写入对象属性的值。 Crystal 有宏,所以为属性定义 getter 和 setter 很容易。 宏是一种在编译期生成代码的方式,后面的宏概念里会讲到。

在 Ruby 中,这些方法用attr_reader、attr_writer和attr_accessor方法定义,表面上和 Crystal 的实现非常相似。 Crystal 则把它们定义成了getter、setter和property宏。

getter

getter 是一个宏,它定义了一个返回实例变量值的方法。 这意味着,当你想访问实例变量时,不必再在它前面写@(在方法里,initialize除外),而是可以调用 getter 宏定义的方法。

getter 宏可以接受多个实例变量,用逗号分隔即可。

# This:
class Person
  @name : String
  @age : Int32

  def name
    @name
  end

  def age
    @age
  end
end

# Is the same as this:
class Person
  @name : String
  @age : Int32

  getter name, :age
end

可以看到,使用 getter 减少了你要写的代码量,也让代码更好读。 另外,Ruby 和 Crystal 还有一个不同之处:Crystal 的 getter 宏既接受变量名,也接受符号作为参数。 符号会在后面的符号概念里讲到。

setter

setter 是一个宏,它定义了一个设置实例变量值的方法。 这个宏并不常见,通常改用property宏。 创建出来的方法形如name_of_method=,正是这个=让属性可以被设置。

这种方法的定义有点特别,因为方法接收的实参写在=后面。 Crystal 中还有几个特殊方法也用这种语法,比如+方法。

和 getter 宏一样,定义了 setter 之后,当你想更新实例变量的值时,可以调用 setter 宏定义的方法。

# This:
class Person
  @name : String
  @age : Int32

  def name=(name : String)
    @name = name
  end

  def age=(age : Int32)
    @age = age
  end
end

# Is the same as this:
class Person
  @name : String
  @age : Int32

  setter name, :age
end

property

property 是一个宏,它为实例变量同时定义 getter 和 setter。

class Person
  @name : String
  @age : Int32

  property name, :age
end

说明

在这个练习中,你将对一台称重机建模。

1. 为称重机创建初始状态

初始化时,称重机应参考其出厂设置,而出厂设置会因机器的销售地区而异。因此,机器在初始化时应能指定一个精度,以及它使用的是公制还是英制。

实现 WeighingMachine#initialize 方法,它接收两个实参:precision(一个 Int32)和 metric(一个 Bool)。metric 实参为 true 时表示机器应使用公制,否则应使用英制。这个初始化方法还应将实例变量 @weight 设为 0.0。

precision = 3
metric = true
vm = WeighingMachine.new(precision, metric)

2. 让称重机具有精度

为了满足不同的需求,我们允许每台称重机自定义精度(小数点后的位数)。

实现 WeighingMachine#precision getter 方法,返回称重机的精度。

precision = 3
metric = true
vm = WeighingMachine.new(precision, metric)
vm.precision
# => 3

3. 允许在称重机上设置重量

实现 WeighingMachine#weight 属性,使重量既能被读取,_也_能被设置:

precision = 3
metric = true
wm = WeighingMachine.new(precision, metric)
wm.weight = 60.5
wm.weight
# => 60.5

wm.weigh
# => 60.5

4. 允许机器在公制和英制单位之间切换

实现 WeighingMachine#metric= 属性来设置单位。它应接受一个布尔值。

precision = 3
metric = true
wm = WeighingMachine.new(precision, metric)
vm.weight = 60.5
wm.metric = false

vm.weigh
# => 133.377
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Crystal Exercism

准备好开始 称重机 了吗?

注册 Exercism,借助 26 个概念142 个练习 和真人导师指导,学习并掌握 Crystal,全部免费。