Balança

Balança

Exercício de aprendizagem

Introdução

Getters e setters são métodos que permitem ler e escrever o valor de uma propriedade de um objeto. O Crystal tem macros, o que facilita definir getters e setters para uma propriedade. Macros são uma forma de gerar código em tempo de compilação, o que será abordado mais adiante no conceito de macros.

No Ruby, esses métodos são definidos com os métodos attr_reader, attr_writer e attr_accessor e, na superfície, são muito parecidos com a implementação do Crystal. O Crystal os definiu como as macros getter, setter e property.

Getters

Getter é uma macro que define um método que retorna o valor de uma variável de instância. Isso significa que você não precisa mais escrever @ na frente da variável de instância quando quiser acessá-la (em métodos, exceto em initialize); em vez disso, você pode chamar o método que a macro getter definiu.

A macro getter pode receber 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 você pode ver, usar o getter reduz a quantidade de código que você escreve e facilita a leitura. Além disso, Ruby e Crystal diferem em um ponto: o Crystal aceita tanto o nome da variável quanto um símbolo como argumentos para a macro getter. Símbolos serão abordados mais adiante no conceito de símbolos.

Setters

Setter é uma macro que define um método que atribui o valor de uma variável de instância. Essa macro não é tão comum; normalmente usa-se a macro property em seu lugar. Os métodos criados terão o formato name_of_method=; é o = que faz com que a propriedade possa ser atribuída.

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

Assim como na macro getter, quando você quiser atualizar o valor de uma variável de instância depois de definir um setter, você pode 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

A macro property define tanto um getter quanto um setter para uma variável de instância.

class Person
  @name : String
  @age : Int32

  property name, :age
end

Instruções

Neste exercício, você vai modelar uma balança.

1. Crie um estado inicial para a balança

Quando inicializada, a balança deve usar as configurações de fábrica, que são diferentes conforme o local onde a máquina é vendida. Por isso, a máquina deve poder ser inicializada com uma precisão e com a indicação de se ela é métrica ou imperial.

Implemente 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, ela 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. Permita que a balança tenha uma precisão

Para atender a demandas diferentes, permitimos que cada balança seja personalizada com uma precisão (o número de dígitos depois do separador decimal).

Implemente o método getter WeighingMachine#precision para retornar a precisão da balança.

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

3. Permita que o peso seja definido na balança

Implemente a propriedade WeighingMachine#weight para permitir que o peso seja lido e definido:

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

wm.weigh
# => 60.5

4. Permita que a máquina alterne entre unidades métricas e imperiais

Implemente a propriedade WeighingMachine#metric= para permitir que a unidade seja definida. Ela deve aceitar um valor Boolean.

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

vm.weigh
# => 133.377
Editar via GitHub O link abre em uma nova janela ou aba
Crystal Exercism

Tudo pronto para começar Balança?

Crie sua conta no Exercism para aprender e dominar Crystal com 26 conceitos142 exercícios e mentoria humana de verdade, tudo de graça.