Menu
Coddy logo textTech

Доступ через замыкания

Часть раздела Объектно-ориентированное программирование путешествия по Lua на Coddy. Урок 45 из 70.

Private local переменные бесполезны, если вы никогда не можете взаимодействовать с ними. Решение — определить getter и setter methods inside constructor, где у них есть доступ к области видимости closure.

Поскольку эти methods создаются inside :new(), они могут «видеть» local переменные. Вы назначаете их directly объекту:

local Counter = {}
Counter.__index = Counter

function Counter:new()
    local count = 0  -- Приватная переменная
    
    local obj = {}
    
    -- Определить методы внутри конструктора
    function obj:getCount()
        return count
    end
    
    function obj:increment()
        count = count + 1
    end
    
    setmetatable(obj, Counter)
    return obj
end

Теперь к закрытой переменной count можно получить доступ, но только через предоставленные вами methods:

local c = Counter:new()
print(c:getCount())  -- 0
c:increment()
c:increment()
print(c:getCount())  -- 2
print(c.count)       -- nil (всё ещё скрыто!)

Обратите внимание, что :getCount() и :increment() определены непосредственно на obj, а не в таблице класса. Каждый экземпляр получает собственную копию этих функций, каждая из которых имеет доступ к своему собственному приватному count. Такова цена: настоящая приватность требует немного больше памяти, поскольку methods не являются общими через прототип.

challenge icon

Задание

Легко

Давайте создадим класс Temperature, который использует приватность на основе замыкания для хранения значения температуры в градусах Цельсия, а методы getter и setter, определённые внутри constructor, обеспечивают контролируемый доступ!

Вы организуете код в двух файлах:

  • Temperature.lua: Создайте class, в котором значение температуры хранится в локальной переменной внутри constructor: оно полностью скрыто от внешнего доступа. Constructor :new(initialCelsius) должен сохранить температуру в локальной переменной, а затем определить следующие methods непосредственно в instance объекта:
    • :getCelsius(): возвращает текущую температуру в градусах Цельсия
    • :setCelsius(value): изменяет температуру на новое значение
    • :getFahrenheit(): возвращает температуру, converted в градусы Фаренгейта, используя Formula: (celsius * 9/5) + 32
  • main.lua: Require ваш модуль Temperature и считайте два значения из input: initial температуру и новую температуру для установки. Create instance Temperature с initial значением, выведите показания в градусах Цельсия и Фаренгейта, затем используйте setter, чтобы изменить температуру, и снова выведите оба показания.

Вы получите два входных значения:

  1. Начальная температура в градусах Цельсия (число)
  2. Новая температура для установки (число)

Ваш вывод должен содержать четыре строки с показаниями температуры до и после change:

Celsius: {initialValue}
Fahrenheit: {convertedInitial}
Celsius: {newValue}
Fahrenheit: {convertedNew}

Например, если входными значениями являются 0 и 100, вывод должен быть таким:

Celsius: 0
Fahrenheit: 32
Celsius: 100
Fahrenheit: 212

Помните: значение температуры должно храниться в локальной переменной внутри :new(), а не в self. Getter и setter methods определяются внутри constructor, где они могут получить доступ к этой private переменной через closure. Попытка напрямую обратиться к temp.celsius или temp._celsius должна возвращать nil!

Попробуйте сами

-- Подключить модуль Temperature
local Temperature = require('Temperature')

-- Прочитать входные значения
local initialTemp = tonumber(io.read())
local newTemp = tonumber(io.read())

-- TODO: Создать экземпляр Temperature с начальным значением

-- TODO: Вывести начальные показания Celsius и Fahrenheit

-- TODO: Использовать сеттер, чтобы изменить температуру на newTemp

-- TODO: Вывести обновлённые показания Celsius и Fahrenheit
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Lua