Menu
Coddy logo textTech

Proste mixiny

Część sekcji Programowanie obiektowe ścieżki Lua w Coddy. Lekcja 51 z 70.

Kompozycja pozwala umieszczać obiekty wewnątrz innych obiektów. A co, jeśli chcesz współdzielić zachowanie między niepowiązanymi klasami?

Zarówno Player, jak i MenuItem mogą potrzebować metody :describe(), ale nie mają wspólnej klasy nadrzędnej. Właśnie wtedy przydają się miksy.

Mixin to po prostu tabela zawierająca funkcje. „Mieszasz” te funkcje z klasą, kopiując je do niej:

local Printable = {}

function Printable:describe()
    print("Object: " .. tostring(self))
end

function Printable:log(message)
    print("[LOG] " .. message)
end

Aby zastosować tę domieszkę do klasy, kopiujesz każdą funkcję z tabeli domieszki do tabeli klasy:

local function applyMixin(class, mixin)
    for key, value in pairs(mixin) do
        class[key] = value
    end
end

local Player = {}
Player.__index = Player

applyMixin(Player, Printable)  -- Teraz Player ma :describe() i :log()

Po zastosowaniu domieszki każda instancja Player może wywoływać te metody tak, jakby były zdefiniowane bezpośrednio w klasie:

local p = setmetatable({}, Player)
p:log("Player created")  -- [LOG] Utworzono gracza

W przeciwieństwie do dziedziczenia miksy nie tworzą relacji rodzic–dziecko. Po prostu kopiujesz funkcje z jednej tabeli do drugiej.

To sprawia, że miksy idealnie nadają się do współdzielenia użytecznych zachowań, takich jak logowanie, serializacja czy metody opisu, między klasami, które poza tym nie mają ze sobą nic wspólnego.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system tagowania z użyciem mixinów! Utworzysz mixin Taggable, który można zastosować do dowolnej klasy, dzięki czemu obiekty będą mogły zarządzać kolekcją tagów przydatnych do kategoryzowania elementów, postów lub dowolnych obiektów wymagających etykiet.

Rozmieścisz kod w trzech plikach:

  • Taggable.lua: Utwórz tabelę mixinu zawierającą dwie metody:
    • :addTag(tag): dodaje tag do self.tags (zakłada, że tabela istnieje)
    • :listTags(): wyświetla wszystkie tagi w formacie Tags: tag1, tag2, tag3 (lub Tags: none, jeśli tabela jest pusta)
  • Article.lua: Utwórz klasę Article z konstruktorem :new(title), który zapisuje tytuł i inicjuje pustą tabelę tags. Zastosuj mixin Taggable, aby instancje Article mogły obsługiwać tagi. Dodaj metodę :getTitle(), która zwraca tytuł artykułu.
  • main.lua: Napisz tutaj funkcję pomocniczą applyMixin (użyjesz jej w Article.lua za pomocą require). Następnie wczytaj tytuł artykułu i dwa tagi. Utwórz obiekt Article, dodaj do niego oba tagi, wyświetl tytuł i wypisz wszystkie tagi.

Otrzymasz trzy dane wejściowe:

  1. Tytuł artykułu (ciąg znaków)
  2. Pierwszy tag do dodania (ciąg znaków)
  3. Drugi tag do dodania (ciąg znaków)

Wynik powinien zawierać tytuł artykułu, a następnie jego tagi:

Title: {title}
Tags: {tag1}, {tag2}

Na przykład, jeśli dane wejściowe to Lua Basics, programming i tutorial, wynik powinien wyglądać tak:

Title: Lua Basics
Tags: programming, tutorial

Pamiętaj: metody mixinu działają, ponieważ instancje Article mają tabelę tags, na której mogą operować metody mixinu. Mixin nie tworzy tej tabeli. Robi to konstruktor Article. Mixin zapewnia jedynie wspólne zachowanie!

Spróbuj swoich sił

-- Główny plik systemu tagowania
local Taggable = require('Taggable')
local Article = require('Article')

-- TODO: Zaimplementuj funkcję applyMixin
-- Ta funkcja powinna skopiować wszystkie metody z tabeli mixin do tabeli target
function applyMixin(target, mixin)
    -- TODO: Przejdź przez tabelę mixin i skopiuj każdą metodę do target
end

-- Odczytaj dane wejściowe
local title = io.read()
local tag1 = io.read()
local tag2 = io.read()

-- TODO: Utwórz Article z podanym tytułem

-- TODO: Dodaj oba tagi do artykułu

-- TODO: Wyświetl tytuł w formacie: Title: {title}

-- TODO: Wyświetl wszystkie tagi za pomocą metody listTags
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Lua online