Parcours
/
Crystal
Crystal
/
Exercices
/
La machine à jus de Johannes
La machine à jus de Johannes

La machine à jus de Johannes

Exercice d'apprentissage

Introduction

Les classes sont un concept central en programmation orientée objet. En Crystal, tout est un objet, chaque objet possède un type et peut répondre à certaines méthodes. Les classes sont des plans qui servent à créer des objets : elles fournissent des valeurs initiales pour l'état, comme les variables, et des implémentations de comportement, comme les méthodes. Les objets sont des instances de classe qui contiennent toutes les variables d'instance et les états.

Définition d'une classe

Une classe se définit à l'aide du mot-clé class, suivi du nom de la classe écrit en UpperCamelCase.

class Account
end

Crée une instance

Pour créer une instance d'une classe, appelle le nom de la classe à l'aide de la méthode new.

class Account
end

account = Account.new

Dans l'exemple ci-dessus, la variable account est une instance de la classe Account.

Lors de la création d'une instance, une méthode spéciale appelée initialize joue le rôle de constructeur. Elle est appelée lorsqu'une instance est créée. Le constructeur permet de définir l'état initial de l'instance. La méthode initialize peut prendre des arguments, qui sont passés lors de la création d'une instance.

class Account
  def initialize(number)
    5 + number # => 9
  end
end

Account.new(4)
Note

La méthode initialize ne peut pas renvoyer de valeur manuellement ; à la place, c'est new qui renvoie l'instance qui vient d'être créée.

class Account
  def initialize(number)
    5 + number
  end
end

Account.new(4)
# => #<Account:0x7f5dc33dcea0>

Méthodes d'instance

Une méthode d'instance est une méthode disponible pour une instance d'une classe, et qui peut être appelée sur cette instance. Les méthodes d'instance se définissent à l'aide du mot-clé def, suivi du nom de la méthode. Elles sont définies à l'intérieur de la définition de la classe.

class Account
  def balance
    100
  end
end

account = Account.new
account.balance # => 100

Variables d'instance

Les variables d'instance sont des variables disponibles dans toutes les méthodes de l'instance. Pour accéder à une variable d'instance, tu dois définir une méthode d'instance. Elles peuvent être initialisées dans la méthode initialize. Elles se définissent à l'aide du préfixe @.

class Account
  def initialize
    @balance = 100
  end

  def balance
    @balance
  end
end

account = Account.new
account.balance
# => 100

Les variables d'instance peuvent aussi être définies directement dans la définition de la classe.

class Account
  @age = 0
end

Variables d'instance avec initialisation

Les variables d'instance peuvent être initialisées avec un argument passé à la méthode initialize. Comme Crystal ne peut pas déduire le type de l'argument utilisé lors de l'initialisation, il faut le préciser. Si tu veux en savoir plus à ce sujet, tu peux lire : l'inférence de type. Pour préciser le type de la variable, tu peux utiliser le symbole :, suivi du type. Par exemple, si tu veux créer une variable d'instance appelée balance de type Int32, tu peux faire comme ceci : @balance : Int32. Ou bien, si tu veux créer une variable d'instance appelée raining de type Bool, tu peux faire comme ceci : @raining : Bool.

Il y a plusieurs façons de faire : soit déclarer l'argument avec son type dans la méthode initialize, puis affecter l'argument à la variable d'instance, comme dans l'exemple suivant :

class Account
  def initialize(balance : Int32)
    @balance = balance
  end

  def balance
    @balance
  end
end

account = Account.new(1)
account_2 = Account.new(5)

account.balance
# => 1

account_2.balance
# => 5

Une autre façon consiste à déclarer le type de la variable d'instance dans la définition de la classe, sous la forme @<variable> : <Type>, comme dans l'exemple suivant :

class Weather

  @raining : Bool

  def initialize(raining)
    @raining = raining
  end

  def raining
    @raining
  end
end

weather = Weather.new(true)
weather.raining
# => true

Modifie les variables d'instance

Les méthodes peuvent modifier les variables d'instance. Ces méthodes peuvent être appelées sur l'instance de la classe. Lorsqu'une méthode modifie une variable d'instance, ce changement n'est visible que dans l'instance de la classe sur laquelle tu l'as appelée.

class Account
  def initialize(balance : Int32)
    @balance = balance
  end

  def withdraw(amount)
    @balance -= amount
  end

  def balance
    @balance
  end
end

account = Account.new(10)
account_2 = Account.new(10)
account.balance
# => 10

account_2.balance
# => 10

account.withdraw(5)
account.balance
# => 5

account_2.balance
# => 10

Méthodes de classe

Les méthodes de classe sont des méthodes définies pour une classe, mais pas pour ses instances. Elles offrent un moyen de créer des méthodes qui ne dépendent pas de l'état de l'instance. Elles se définissent à l'aide du mot-clé def, suivi de self.<method name>. self est une référence à l'espace de noms depuis lequel self est appelé. Ici, il désigne la classe Account. Cela reviendrait au même que d'écrire Account., mais self. est la façon privilégiée.

class Account
  def self.balance
    100
  end
end

Account.balance
# => 100

Instructions

Ton ami Johannes adore fabriquer son propre matériel en DIY (do it yourself). Johannes vient de construire un extracteur de jus et en est très enthousiaste. L'objectif de Johannes est de pouvoir préparer du jus frais chaque matin.

L'extracteur de jus de Johannes a de nombreuses fonctionnalités sophistiquées. Comme un système de mesure intégré, qui peut t'indiquer la quantité de jus dans le verre. Il a aussi un minuteur, qui t'indique depuis combien de temps la machine tourne.

Johannes n'est pas très doué en programmation, mais il veut écrire un programme pour contrôler la machine. C'est pourquoi il t'a demandé de l'aider.

1. Voyant de débogage

La machine possède un voyant de débogage, c'est un mécanisme simple : si la machine est alimentée, le voyant de débogage est allumé. Le programme ne s'exécute que si le voyant de débogage est allumé.

Cette méthode doit être une méthode de classe appelée JuiceMaker.

Définis la méthode de classe JuiceMaker.debug_light_on? qui renvoie true.

JuiceMaker.debug_light_on?
#=> true

2. Initialiser la machine

Quand la machine est allumée, elle doit créer une instance d'une classe appelée JuiceMaker. La machine est censée avoir un état initialisé. L'état initialisé doit contenir les informations suivantes :

  1. Si la machine est en marche ou non. Cette valeur doit toujours être false quand la machine est allumée.
  2. La quantité de jus dans le verre, ce sera un capteur qui mesure la quantité de jus dans le verre.

Définis l'état initialisé, qui prend en paramètre la quantité de jus dans le verre, et construis cet état initialisé. L'état initialisé doit comporter une variable d'instance @running qui vaut false, et une variable d'instance @fluid qui se base sur un argument fourni lors de l'initialisation de la classe.

JuiceMaker.new(5)
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=5>

3. Allumer la machine

La machine peut être allumée et éteinte. Tu dois définir une méthode pour allumer la machine. Quand la machine est allumée, l'état de marche doit être défini à true.

Définis la méthode JuiceMaker#start qui allume la machine.

juice_maker = JuiceMaker.new(5)
juice_maker.start

juice_maker
#=> #<JuiceMaker:0x10f0b8 @running=true, @fluid=5>

4. État de la machine

La machine doit pouvoir t'indiquer son état. Elle doit renvoyer true si la machine est en marche, et false si la machine n'est pas en marche.

Définis la méthode JuiceMaker#running? qui renvoie l'état de la machine.

juice_maker = JuiceMaker.new(5)
juice_maker.start

juice_maker.running?
#=> true

5. Ajouter du jus

La machine peut ajouter du jus dans le verre. La machine peut déterminer la quantité de jus ajoutée au verre. La machine a besoin d'aide pour savoir quelle quantité de jus se trouve dans le verre une fois le jus ajouté.

Définis la méthode JuiceMaker#add_fluid, qui prend en paramètre la quantité de jus ajoutée et met à jour la quantité de jus dans le verre.

juice_maker = JuiceMaker.new(5)
juice_maker.add_fluid(5)

juice_maker
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=10>

6. Éteindre la machine

La machine peut être allumée et éteinte. Tu dois définir une méthode pour éteindre la machine Cette méthode ne sera appelée que lorsque la machine est en marche. Quand la machine est éteinte, l'état de marche doit être défini à false. La machine a aussi besoin d'aide pour déterminer la quantité de jus qui reste dans le verre après son extinction. La machine consomme cinq unités de jus par minute.

Définis la méthode JuiceMaker#stop qui prend en paramètre le nombre de minutes pendant lesquelles la machine a tourné et qui renvoie la quantité de jus présente dans le verre une fois la machine éteinte.

juice_maker = JuiceMaker.new(5)

juice_maker.start
juice_maker
#=> <JuiceMaker:0x10f0b8 @running=true, @fluid=5>

juice_maker.stop(1)
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=0>
Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet
Crystal Exercism

Prêt à commencer La machine à jus de Johannes ?

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