Balança

Balança

Exercício de aprendizagem

Introdução

Os getters e os setters são métodos que te permitem ler e escrever o valor de uma propriedade de um objeto. O Crystal tem macros, o que torna mais fácil definir getters e setters para uma propriedade. As macros são uma forma de gerar código em tempo de compilação, algo que será abordado mais à frente no conceito de macros.

Em Ruby, estes métodos são definidos com os métodos attr_reader, attr_writer e attr_accessor e, à superfície, são muito semelhantes à implementação do Crystal. O Crystal definiu-os como as macros getter, setter e property.

Getters

Getter é uma macro que define um método que devolve o valor de uma variável de instância. Isto significa que já não precisas de escrever @ antes da variável de instância quando queres aceder-lhe (em métodos, exceto no initialize); em vez disso, podes chamar o método que a macro getter definiu.

A macro getter pode aceitar várias variáveis de instância, separando-as por vírgulas.

# 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

Como podes ver, usar getter reduz a quantidade de código que escreves e torna-o mais fácil de ler. Além disso, o Ruby e o Crystal diferem no facto de o Crystal aceitar tanto o nome da variável como o símbolo como argumentos para a macro getter. Os símbolos serão abordados mais à frente no conceito de símbolos.

Setters

Setter é uma macro que define um método que atribui o valor a uma variável de instância. Esta macro não é muito comum e, em vez dela, costuma usar-se a macro property. Os métodos criados terão o aspeto name_of_method=; é o = que faz com que a propriedade possa ser definida.

Esta definição de método é um pouco especial, pois o argumento que o método recebe vem depois do sinal =. Vários outros métodos especiais do Crystal usam esta sintaxe, como o método +.

Tal como acontece com a macro getter, quando queres atualizar o valor de uma variável de instância depois de definires um setter, podes chamar o método que a macro setter definiu.

# 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 é uma macro que define tanto um getter como um setter para uma variável de instância.

class Person
  @name : String
  @age : Int32

  property name, :age
end

Instruções

Neste exercício vais modelar uma máquina de pesagem.

1. Cria um estado inicial para a máquina de pesagem

Quando é inicializada, a máquina de pesagem deve usar as suas configurações de fábrica, que são diferentes consoante o sítio onde a máquina é vendida. Além disso, a máquina deve poder ser inicializada com uma precisão e com a indicação de se usa o sistema métrico ou o imperial.

Implementa o método WeighingMachine#initialize, que recebe dois argumentos: precision, que é um Int32, e metric, que é um Bool. O argumento metric, quando é true, significa que a máquina deve usar o sistema métrico; caso contrário, deve usar o sistema imperial. O método initialize também deve definir a variável de instância @weight como 0.0.

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

2. Permite que a máquina de pesagem tenha uma precisão

Para responder a exigências diferentes, permitimos que cada máquina de pesagem seja personalizada com uma precisão (o número de algarismos depois do separador decimal).

Implementa o método getter WeighingMachine#precision para devolver a precisão da máquina de pesagem.

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

3. Permite definir o peso na máquina de pesagem

Implementa a propriedade WeighingMachine#weight para permitir obter e definir o peso:

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

wm.weigh
# => 60.5

4. Permite alternar a máquina entre as unidades métrica e imperial

Implementa a propriedade WeighingMachine#metric= para permitir definir a unidade. Deve aceitar um valor do tipo Boolean.

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

vm.weigh
# => 133.377
Editar via GitHub A ligação abre numa nova janela ou separador
Crystal Exercism

Estás pronto para começar Balança?

Inscreve-te no Exercism para aprenderes e dominares Crystal com 26 conceitos142 exercícios, e mentoria humana real, tudo grátis.