Треки
/
Crystal
Crystal
/
Вправи
/
Соковижималка Йоганнеса
Соковижималка Йоганнеса

Соковижималка Йоганнеса

Навчальна вправа

Вступ

Класи - центральне поняття обʼєктно-орієнтованого програмування. У Crystal усе є обʼєктом, кожен обʼєкт має тип і може відповідати на деякі методи. Класи - це креслення для створення обʼєктів: вони задають початкові значення для стану, як-от змінні, і реалізації поведінки, як-от методи. Обʼєкти - це екземпляри класу, які зберігають усі змінні екземпляра та стани.

Визначення класу

Клас визначають за допомогою ключового слова class, після якого йде назва класу, записана в UpperCamelCase.

class Account
end

Створення екземпляра

Щоб створити екземпляр класу, викликаємо назву класу за допомогою методу new.

class Account
end

account = Account.new

У наведеному вище прикладі змінна account - це екземпляр класу Account.

Під час створення екземпляра спеціальний метод initialize виконує роль конструктора. Його викликають під час створення екземпляра. Конструктор дає змогу задати початковий стан екземпляра. Метод initialize може приймати аргументи, які передаються під час створення екземпляра.

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

Account.new(4)
Note

Метод initialize не може повертати значення вручну; натомість new повертає щойно створений екземпляр.

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

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

Методи екземпляра

Метод екземпляра - це метод, доступний екземпляру класу, який можна викликати на цьому екземплярі. Методи екземпляра визначають за допомогою ключового слова def, після якого йде назва методу. Їх визначають усередині визначення класу.

class Account
  def balance
    100
  end
end

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

Змінні екземпляра

Змінні екземпляра - це змінні, доступні в усіх методах екземпляра. Щоб отримати доступ до змінної екземпляра, треба визначити метод екземпляра. Їх можна ініціалізувати в методі initialize. Їх визначають за допомогою префікса @.

class Account
  def initialize
    @balance = 100
  end

  def balance
    @balance
  end
end

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

Змінні екземпляра також можна визначити всередині визначення класу.

class Account
  @age = 0
end

Змінні екземпляра з ініціалізацією

Змінні екземпляра можна ініціалізувати аргументом, переданим у метод initialize. Оскільки Crystal не може вивести тип аргументу, використаного під час ініціалізації, його потрібно вказати. Докладніше про це можна прочитати тут: виведення типу. Щоб указати тип змінної, можна використати символ :, після якого йде тип. Наприклад, щоб створити змінну екземпляра з назвою balance типу Int32, можна зробити так: @balance : Int32. Або, щоб створити змінну екземпляра з назвою raining типу Bool, можна зробити так: @raining : Bool.

Є кілька способів це зробити: або оголосити аргумент із типом у методі initialize, а потім присвоїти змінній екземпляра значення аргументу, як у наступному прикладі:

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

Інший спосіб - оголосити тип змінної екземпляра у визначенні класу у формі: @<variable> : <Type>, як у наступному прикладі:

class Weather

  @raining : Bool

  def initialize(raining)
    @raining = raining
  end

  def raining
    @raining
  end
end

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

Зміна змінних екземпляра

Методи можуть змінювати змінні екземпляра. Ці методи можна викликати на екземплярі класу. Коли метод змінює змінну екземпляра, ця зміна доступна лише в тому екземплярі класу, на якому його викликали.

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

Методи класу

Методи класу - це методи, визначені для класу, а не для його екземплярів. Вони дають змогу створювати методи, які не залежать від стану екземпляра. Їх визначають за допомогою ключового слова def, після якого йде self.<method name>. self - це посилання на простір імен, з якого викликають self. У цьому випадку він указує на клас Account. Це те саме, якби написати Account., але краще використовувати self..

class Account
  def self.balance
    100
  end
end

Account.balance
# => 100

Вказівки

Друг Йоганнес обожнює збирати саморобну апаратуру (DIY, тобто «зроби сам»). Він щойно зібрав соковижималку і дуже нею захоплений. Мета Йоганнеса - щоранку готувати свіжий сік.

У соковижималки Йоганнеса багато цікавих можливостей. Наприклад, вбудована система вимірювання, яка показує, скільки соку в склянці. Є в неї й таймер, який підказує, як довго працює машина.

Йоганнес не дуже добре програмує, але хоче написати програму для керування машиною. Тож він і попросив допомогти.

1. Індикатор debug

У машини є індикатор debug. Це простий механізм: якщо машина має живлення, індикатор debug горить. Програма запуститься, лише якщо індикатор debug горить.

Цей метод має бути методом класу з назвою JuiceMaker.

Визначте метод класу JuiceMaker.debug_light_on?, який повертає true.

JuiceMaker.debug_light_on?
#=> true

2. Ініціалізація машини

Коли машина вмикається, має створюватися екземпляр класу з назвою JuiceMaker. Машина повинна мати ініціалізований стан. Ініціалізований стан має містити таку інформацію:

  1. Чи працює машина. Коли машина вмикається, це значення має завжди бути false.
  2. Кількість соку в склянці; це буде сенсор, який вимірюватиме кількість соку в склянці.

Визначте ініціалізований стан, який приймає кількість соку в склянці як параметр, і сконструюйте цей стан. Ініціалізований стан має містити змінну екземпляра @running, встановлену в false, і змінну екземпляра @fluid, значення якої базується на аргументі, переданому під час ініціалізації класу.

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

3. Увімкнення машини

Машину можна вмикати й вимикати. Потрібно визначити метод, який вмикає машину. Коли машина вмикається, стан роботи має встановлюватися в true.

Визначте метод JuiceMaker#start, який вмикає машину.

juice_maker = JuiceMaker.new(5)
juice_maker.start

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

4. Стан машини

Машина повинна вміти повідомляти свій стан. Він має повертати true, якщо машина працює, і false, якщо машина не працює.

Визначте метод JuiceMaker#running?, який повертає стан машини.

juice_maker = JuiceMaker.new(5)
juice_maker.start

juice_maker.running?
#=> true

5. Додавання соку

Машина може додавати сік у склянку. Машина вміє визначати, скільки соку додано в склянку. Але їй потрібна допомога, щоб дізнатися, скільки соку в склянці після додавання.

Визначте метод JuiceMaker#add_fluid, який приймає кількість доданого соку як параметр і оновлює кількість соку в склянці.

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

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

6. Вимкнення машини

Машину можна вмикати й вимикати. Потрібно визначити метод, який вимикає машину. Цей метод викликатиметься лише тоді, коли машина працює. Коли машина вимикається, стан роботи має встановлюватися в false. Також машині потрібна допомога, щоб визначити, скільки соку в склянці після вимкнення. Машина витрачає пʼять одиниць соку за хвилину.

Визначте метод JuiceMaker#stop, який приймає кількість хвилин роботи машини як параметр і повертає кількість соку в склянці після вимкнення машини.

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>
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Crystal Exercism

Час розпочати Соковижималка Йоганнеса?

Зареєструйтеся на Exercism, щоб вивчати й опановувати Crystal, а також 26 концепцій142 вправи та справжнє наставництво від людей, і все це безкоштовно.