Ваги

Ваги

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

Вступ

Гетери та сетери - це методи, які дозволяють читати й записувати значення властивості обʼєкта. У Crystal є макроси, завдяки яким легко визначати гетери та сетери для властивості. Макроси - це спосіб генерувати код під час компіляції, про що йтиметься пізніше в концепції макросів.

У Ruby ці методи визначають за допомогою методів attr_reader, attr_writer та attr_accessor, і зовні вони дуже схожі на реалізацію в Crystal. У Crystal їх визначено як макроси getter, setter і property.

Гетери

getter - це макрос, який визначає метод, що повертає значення змінної екземпляра. Це означає, що більше не потрібно писати @ перед змінною екземпляра, коли ми хочемо отримати до неї доступ (у методах, крім initialize); натомість можна викликати метод, який визначив макрос getter.

Макрос getter може приймати кілька змінних екземпляра, розділених комами.

# 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

Як бачимо, використання getter зменшує обсяг коду, який ми пишемо, і робить його легшим для читання. Крім того, Ruby та Crystal відрізняються тим, що Crystal приймає і назву змінної, і symbol як аргументи для макросу getter. Символи буде розглянуто пізніше в концепції symbol.

Сетери

setter - це макрос, який визначає метод, що встановлює значення змінної екземпляра. Цей макрос трапляється нечасто, і зазвичай замість нього використовують макрос property. Методи, які буде створено, матимуть вигляд name_of_method=; саме = робить так, що властивість можна встановити.

Це визначення методу трохи особливе, бо аргумент, який отримує метод, стоїть після знака =. Кілька інших особливих методів у Crystal використовують цей синтаксис, наприклад метод +.

Як і з макросом getter, коли ми хочемо оновити значення змінної екземпляра після визначення setter, можна викликати метод, який визначив макрос setter.

# 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 - це макрос, який визначає і гетер, і сетер для змінної екземпляра.

class Person
  @name : String
  @age : Int32

  property name, :age
end

Вказівки

У цій вправі ми змоделюємо машину для зважування.

1. Створіть початковий стан для машини для зважування

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

Реалізуйте метод WeighingMachine#initialize, який приймає два аргументи: precision типу Int32 і metric типу Bool. Аргумент metric зі значенням true означає, що машина має використовувати метричну систему, інакше вона має використовувати імперську. Метод initialize також має встановити значення змінної екземпляра @weight рівним 0.0.

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

2. Дозвольте задавати точність машини для зважування

Щоб задовольнити різні потреби, кожну машину для зважування можна налаштувати з певною точністю (кількістю цифр після десяткового розділювача).

Реалізуйте метод-гетер WeighingMachine#precision, який повертає точність машини для зважування.

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

3. Дозвольте встановлювати вагу на машині для зважування

Реалізуйте властивість WeighingMachine#weight, щоб вагу можна було і читати, і встановлювати:

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

wm.weigh
# => 60.5

4. Дозвольте перемикати машину між метричною та імперською системами одиниць

Реалізуйте властивість WeighingMachine#metric=, щоб можна було змінювати одиниці вимірювання. Вона має приймати булеве значення (англ. Boolean).

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

vm.weigh
# => 133.377
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Crystal Exercism

Час розпочати Ваги?

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