Menu
Coddy logo textTech

Relacja Has-A

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

W trakcie tego kursu używałeś dziedziczenia, aby współdzielić zachowanie między klasami: pies „jest” zwierzęciem. Jednak dziedziczenie nie zawsze jest odpowiednim narzędziem.

Czasami obiekty nie dzielą wspólnego drzewa rodzinnego; zamiast tego jeden obiekt po prostu zawiera inny. Nazywa się to kompozycją i modeluje relację „ma”.

Weźmy samochód. Samochód nie jest rodzajem silnika. Ma silnik. Silnik to osobny obiekt, który znajduje się w samochodzie:

local Engine = {}
Engine.__index = Engine

function Engine:new(horsepower)
    local obj = {horsepower = horsepower}
    setmetatable(obj, Engine)
    return obj
end

local Car = {}
Car.__index = Car

function Car:new(model, engine)
    local obj = {
        model = model,
        engine = engine  -- Przechowuj obiekt Engine wewnątrz Car
    }
    setmetatable(obj, Car)
    return obj
end

Podczas tworzenia samochodu przekazujesz istniejący obiekt silnika do jego konstruktora:

local myEngine = Engine:new(200)
local myCar = Car:new("Sedan", myEngine)

print(myCar.engine.horsepower)  -- 200

Samochód nie dziedziczy po silniku. Po prostu przechowuje do niego referencję. Dzięki temu obie klasy pozostają niezależne. Możesz podmienić silnik na inny albo użyć tej samej klasy silnika w motocyklu.

Kompozycja daje ci elastyczność, której nie zapewnia dziedziczenie: składasz obiekty z części, zamiast zamykać je w sztywnej hierarchii rodzinnej.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system komputerowy z użyciem kompozycji! Zamiast dziedziczenia utworzysz Computer, który ma w sobie CPU: demonstrując relację „ma”.

Rozmieścisz kod w trzech plikach:

  • CPU.lua: Utwórz klasę CPU z konstruktorem :new(brand, speed), który przechowuje nazwę marki i szybkość w GHz. Dodaj metodę :getInfo(), która zwraca ciąg znaków w formacie: {brand} @ {speed}GHz
  • Computer.lua: Utwórz klasę Computer, której konstruktor :new(model, cpu) przyjmuje nazwę modelu i obiekt CPU. Computer przechowuje obiekt CPU wewnątrz siebie (kompozycja!). Dodaj metodę :describe(), która wyświetla model komputera i informacje o jego CPU.
  • main.lua: Połącz wszystko w całość! Wczytaj dane wejściowe dotyczące marki CPU, szybkości CPU i modelu komputera. Najpierw utwórz obiekt CPU, a następnie przekaż go do konstruktora Computer. Na koniec wywołaj metodę :describe() komputera.

Otrzymasz trzy dane wejściowe:

  1. Marka CPU (ciąg znaków)
  2. Szybkość CPU w GHz (liczba)
  3. Nazwa modelu komputera (ciąg znaków)

Wynik powinien przedstawiać opis komputera, który zawiera informacje o zawartym w nim CPU:

Model: {model}
CPU: {brand} @ {speed}GHz

Na przykład, jeśli danymi wejściowymi są Intel, 3.5 i WorkStation, wynikiem powinno być:

Model: WorkStation
CPU: Intel @ 3.5GHz

Zwróć uwagę, że Computer nie dziedziczy po CPU. Po prostu przechowuje do niego referencję. Metoda :describe() klasy Computer uzyskuje dostęp do danych CPU za pośrednictwem przechowywanego obiektu, pokazując, jak kompozycja pozwala budować złożone obiekty z prostszych części!

Spróbuj swoich sił

-- main.lua
-- Połącz wszystko za pomocą kompozycji

local CPU = require('CPU')
local Computer = require('Computer')

-- Odczytaj dane wejściowe
local cpuBrand = io.read()
local cpuSpeed = tonumber(io.read())
local computerModel = io.read()

-- TODO: Utwórz obiekt CPU z podaną marką i szybkością

-- TODO: Utwórz obiekt Computer z podanym modelem i obiektem CPU

-- TODO: Wywołaj metodę describe() obiektu Computer, aby wyświetlić wynik
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