Balance

Balance

Exercice d'apprentissage

Introduction

Les getters et les setters sont des méthodes qui permettent de lire et d'écrire la valeur d'une propriété d'un objet. Crystal dispose de macros, ce qui facilite la définition de getters et de setters pour une propriété. Les macros permettent de générer du code à la compilation, un sujet que nous aborderons plus tard dans le concept sur les macros.

En Ruby, ces méthodes se définissent avec les méthodes attr_reader, attr_writer et attr_accessor, et elles ressemblent beaucoup, en apparence, à l'implémentation qu'en fait Crystal. Crystal les a définies sous forme de macros getter, setter et property.

Getters

getter est une macro qui définit une méthode renvoyant la valeur d'une variable d'instance. On n'a donc plus besoin d'écrire @ devant la variable d'instance pour y accéder (dans les méthodes, sauf initialize), il suffit d'appeler la méthode définie par la macro getter.

La macro getter accepte plusieurs variables d'instance, à séparer par des virgules.

# 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

Comme tu peux le voir, utiliser getter réduit la quantité de code à écrire et le rend plus facile à lire. Autre différence entre Ruby et Crystal : Crystal accepte aussi bien le nom de la variable que le symbole comme arguments de la macro getter. Les symboles seront traités plus tard, dans le concept sur les symboles.

Setters

setter est une macro qui définit une méthode chargée d'affecter une valeur à une variable d'instance. Cette macro est assez rare : c'est en général la macro property que l'on utilise à la place. Les méthodes ainsi créées ressemblent à name_of_method= ; c'est le = qui permet de définir la propriété.

Cette définition de méthode est un peu particulière, car l'argument reçu par la méthode vient après le signe =. Plusieurs autres méthodes particulières de Crystal utilisent cette syntaxe, comme la méthode +.

Comme pour la macro getter, une fois le setter défini, tu peux appeler la méthode créée par cette macro pour mettre à jour la valeur d'une variable d'instance.

# 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 est une macro qui définit à la fois un getter et un setter pour une variable d'instance.

class Person
  @name : String
  @age : Int32

  property name, :age
end

Instructions

Dans cet exercice, on va modéliser une balance.

1. Crée un état initial pour la balance

Une fois initialisée, la balance doit partir de ses réglages d'usine, qui diffèrent selon l'endroit où la machine est vendue. La machine doit donc pouvoir être initialisée avec une précision et en précisant si elle utilise le système métrique ou le système impérial.

Implémente la méthode WeighingMachine#initialize, qui prend deux arguments : precision, qui est un Int32, et metric, qui est un Bool. L'argument metric, lorsqu'il vaut true, signifie que la machine doit utiliser le système métrique ; sinon, elle doit utiliser le système impérial. La méthode d'initialisation doit également affecter la valeur 0.0 à la variable d'instance @weight.

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

2. Permets à la balance d'avoir une précision

Pour répondre à des besoins différents, on permet de personnaliser chaque balance avec une précision (le nombre de chiffres après le séparateur décimal).

Implémente la méthode getter WeighingMachine#precision, qui renvoie la précision de la balance.

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

3. Permets de définir le poids sur la balance

Implémente la propriété WeighingMachine#weight pour permettre de lire et de définir le poids :

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

wm.weigh
# => 60.5

4. Permets à la machine de basculer entre les unités métriques et impériales

Implémente la propriété WeighingMachine#metric= pour permettre de définir l'unité. Elle doit accepter une valeur booléenne.

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

vm.weigh
# => 133.377
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Crystal Exercism

Prêt à commencer Balance ?

Inscris-toi sur Exercism pour apprendre et maîtriser Crystal avec 26 concepts142 exercices, et un vrai mentorat humain, le tout gratuitement.