Menu
Coddy logo textTech

Applying Multiple Mixins

Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 52 of 70.

A single mixin adds one set of behaviors to a class. But real objects often need capabilities from multiple sources. A game object might need to move around and be visible on screen—two separate concerns that don't belong in the same mixin.

The solution is straightforward: apply multiple mixins to the same class. Each mixin contributes its own methods, and the class ends up with all of them:

local Movable = {}
function Movable:move(dx, dy)
    self.x = self.x + dx
    self.y = self.y + dy
end

local Visible = {}
function Visible:show()
    print("Showing at " .. self.x .. ", " .. self.y)
end
function Visible:hide()
    print("Hidden")
end

Apply both mixins to your class using the same helper function from before:

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

local GameObject = {}
GameObject.__index = GameObject

applyMixin(GameObject, Movable)
applyMixin(GameObject, Visible)

Now GameObject instances can both move and display themselves:

local obj = setmetatable({x = 0, y = 0}, GameObject)
obj:move(5, 3)
obj:show()  -- Showing at 5, 3

One caution: if two mixins define the same method name, the second one applied will overwrite the first. Keep your mixin methods distinct to avoid unexpected behavior.

challenge icon

Challenge

Easy

Let's build a Character class for a game that combines multiple capabilities using mixins! Your character will be able to both attack enemies and heal itself—two distinct behaviors that come from separate mixins.

You'll organize your code across four files:

  • Attacker.lua: Create a mixin with an :attack(targetName) method that prints {self.name} attacks {targetName} for {self.damage} damage! (assumes the object has name and damage fields)
  • Healer.lua: Create a mixin with a :heal(amount) method that adds the amount to self.health and prints {self.name} heals for {amount}. Health: {newHealth}
  • Character.lua: Create a Character class with a constructor :new(name, health, damage) that stores all three attributes. Apply both the Attacker and Healer mixins so every character can attack and heal. Include a :status() method that prints {name} - Health: {health}, Damage: {damage}
  • main.lua: Write the applyMixin helper function here. Read inputs for a character's name, health, damage, a target to attack, and a heal amount. Create a Character, show their status, have them attack the target, heal themselves, then show their status again.

You will receive five inputs:

  1. Character name (a string)
  2. Starting health (a number)
  3. Damage value (a number)
  4. Target name to attack (a string)
  5. Amount to heal (a number)

Your output should show the character using both mixin abilities:

{name} - Health: {health}, Damage: {damage}
{name} attacks {target} for {damage} damage!
{name} heals for {healAmount}. Health: {newHealth}
{name} - Health: {newHealth}, Damage: {damage}

For example, if the inputs are Warrior, 100, 25, Goblin, and 30, the output should be:

Warrior - Health: 100, Damage: 25
Warrior attacks Goblin for 25 damage!
Warrior heals for 30. Health: 130
Warrior - Health: 130, Damage: 25

Each mixin contributes its own method to the Character class. The character doesn't inherit from either mixin—it simply gains their abilities through the applyMixin function. This is the power of combining multiple mixins!

Cheat sheet

Multiple mixins can be applied to a single class to combine different sets of behaviors. Each mixin contributes its own methods to the class.

Define separate mixins for different concerns:

local Movable = {}
function Movable:move(dx, dy)
    self.x = self.x + dx
    self.y = self.y + dy
end

local Visible = {}
function Visible:show()
    print("Showing at " .. self.x .. ", " .. self.y)
end
function Visible:hide()
    print("Hidden")
end

Apply multiple mixins to a class using the applyMixin helper function:

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

local GameObject = {}
GameObject.__index = GameObject

applyMixin(GameObject, Movable)
applyMixin(GameObject, Visible)

The class now has methods from all applied mixins:

local obj = setmetatable({x = 0, y = 0}, GameObject)
obj:move(5, 3)
obj:show()  -- Showing at 5, 3

Important: If two mixins define the same method name, the second mixin applied will overwrite the first. Keep method names distinct across mixins to avoid conflicts.

Try it yourself

-- Main file

-- TODO: Write the applyMixin helper function
-- This function should copy all methods from a mixin table to a target table
local function applyMixin(target, mixin)
    -- TODO: Implement mixin application
end

-- Make applyMixin available globally so Character.lua can use it
_G.applyMixin = applyMixin

local Character = require('Character')

-- Read inputs
local name = io.read()
local health = tonumber(io.read())
local damage = tonumber(io.read())
local targetName = io.read()
local healAmount = tonumber(io.read())

-- TODO: Create a Character with the given name, health, and damage

-- TODO: Show the character's status

-- TODO: Have the character attack the target

-- TODO: Have the character heal themselves

-- TODO: Show the character's status again
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming