Menu
Coddy logo textTech

Shared vs Unique

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

When working with inheritance, it's important to understand where each piece of data lives. Some attributes are shared—defined in the parent and accessible to all children. Others are unique—created specifically in the child class or instance.

Consider this hierarchy:

local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia"  -- Shared: defined on the class

function Animal:new(name)
    local obj = {name = name}  -- Unique: stored on each instance
    setmetatable(obj, Animal)
    return obj
end
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark"  -- Shared among all Dogs

function Dog:new(name, breed)
    local obj = Animal.new(Animal, name)
    obj.breed = breed  -- Unique: each Dog has its own breed
    setmetatable(obj, Dog)
    return obj
end

When you create a Dog instance, some values exist directly on the object while others are found through the lookup chain:

local rex = Dog:new("Rex", "German Shepherd")

-- Unique to this instance (stored on rex)
print(rex.name)    -- "Rex"
print(rex.breed)   -- "German Shepherd"
-- Shared (found via lookup)
print(rex.sound)   -- "bark" (from Dog)
print(rex.kingdom) -- "Animalia" (from Animal)

The key distinction: fields assigned to obj in constructors are unique to each instance, while fields defined directly on class tables are shared across all instances of that class and its children.

challenge icon

Challenge

Easy

Let's explore how data flows through an inheritance hierarchy by building a Creature and Dragon class system. You'll see firsthand which attributes are shared across all instances and which are unique to each individual object.

You'll organize your code across three files:

  • Creature.lua: Define your parent class with a shared class-level attribute world = "Fantasy Realm" that all creatures share. Include a :new(name) constructor that stores the creature's name as an instance attribute.
  • Dragon.lua: Define your child class that inherits from Creature. Add a shared class-level attribute element = "fire" that all dragons share. Your :new(name, color) constructor should call the parent constructor for the name, then add color as a unique instance attribute for each dragon.
  • main.lua: Create two different dragons and inspect their attributes to demonstrate the difference between shared and unique data.

You will receive two inputs:

  1. The first dragon's name and color, separated by a comma (e.g., Smaug,red)
  2. The second dragon's name and color, separated by a comma (e.g., Draco,gold)

In your main file, create both dragons with their respective names and colors. Then print the following information in this exact order:

  1. First dragon's name
  2. First dragon's color
  3. Second dragon's name
  4. Second dragon's color
  5. First dragon's element (shared from Dragon class)
  6. Second dragon's element (shared from Dragon class)
  7. First dragon's world (shared from Creature class)

For example, if the inputs are Smaug,red and Draco,gold, the output should be:

Smaug
red
Draco
gold
fire
fire
Fantasy Realm

Notice how name and color are different for each dragon (unique instance attributes), while element and world are the same for both (shared class attributes found through the lookup chain).

Cheat sheet

In inheritance hierarchies, attributes can be either shared (defined on the class table) or unique (stored on individual instances).

Shared attributes are defined directly on class tables and accessed through the metatable lookup chain:

local Animal = {}
Animal.__index = Animal
Animal.kingdom = "Animalia"  -- Shared across all Animals

Unique attributes are assigned to the instance object (obj) in constructors:

function Animal:new(name)
    local obj = {name = name}  -- Unique to each instance
    setmetatable(obj, Animal)
    return obj
end

Child classes can have their own shared attributes while inheriting parent attributes:

local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
Dog.sound = "bark"  -- Shared among all Dogs

function Dog:new(name, breed)
    local obj = Animal.new(Animal, name)  -- Call parent constructor
    obj.breed = breed  -- Add unique child attribute
    setmetatable(obj, Dog)
    return obj
end

Accessing attributes:

local rex = Dog:new("Rex", "German Shepherd")

-- Unique (stored directly on rex)
print(rex.name)    -- "Rex"
print(rex.breed)   -- "German Shepherd"

-- Shared (found via metatable lookup)
print(rex.sound)   -- "bark" (from Dog class)
print(rex.kingdom) -- "Animalia" (from Animal class)

Try it yourself

-- main.lua: Create dragons and demonstrate shared vs unique attributes

local Dragon = require('Dragon')

-- Read input for first dragon (name,color)
local input1 = io.read()
-- Read input for second dragon (name,color)
local input2 = io.read()

-- TODO: Parse the first input to extract name and color
-- Hint: Use string.match with pattern "([^,]+),([^,]+)"

-- TODO: Parse the second input to extract name and color

-- TODO: Create the first dragon with its name and color

-- TODO: Create the second dragon with its name and color

-- TODO: Print the following in order:
-- 1. First dragon's name
-- 2. First dragon's color
-- 3. Second dragon's name
-- 4. Second dragon's color
-- 5. First dragon's element (shared from Dragon class)
-- 6. Second dragon's element (shared from Dragon class)
-- 7. First dragon's world (shared from Creature class)
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