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.
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.
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
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
Neste exercício, você vai modelar uma 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)
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
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
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
Crie sua conta no Exercism para aprender e dominar Crystal com 26 conceitos142 exercícios e mentoria humana de verdade, tudo de graça.