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
endlocal 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
endWhen 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
EasyLet'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 attributeworld = "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 attributeelement = "fire"that all dragons share. Your:new(name, color)constructor should call the parent constructor for the name, then addcoloras 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:
- The first dragon's name and color, separated by a comma (e.g.,
Smaug,red) - 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:
- First dragon's
name - First dragon's
color - Second dragon's
name - Second dragon's
color - First dragon's
element(shared from Dragon class) - Second dragon's
element(shared from Dragon class) - 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 RealmNotice 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 AnimalsUnique 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
endChild 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
endAccessing 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)
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1The 'Self' Concept
Tables with FunctionsExplicit 'self'The Colon SyntaxDot vs ColonRecap - Moving Point4Project: Digital Bank
Project SetupDeposit Method7Polymorphism & Overriding
Overriding MethodsCalling Parent MethodsDuck TypingCommon InterfaceChecking TypeRecap - Employee Roles10Project: Shape Manager
Project SetupRectangle Class2Class Prototype Pattern
The Prototype ConceptLinking with __indexThe :new() ConstructorInitializing AttributesIndependent InstancesRecap - Car Factory5Operator Overloading in OOP
Adding ObjectsSubtracting ObjectsConcatenating ObjectsComparing Objects (<, >)Recap - Wallet Math8Encapsulation
Naming ConventionsClosures for PrivacyAccess via ClosuresRead-Only TablesValidation LogicRecap - Secure Vault11Design Patterns (Lite)
Factory FunctionsSingleton TableIterator PatternObserver (Listener)Recap - Logger Factory3Object State and Behavior
Instance VariablesGetter MethodsSetter MethodsCalculated PropertiesFormatting StringsEquality ChecksRecap - Student Grade6Inheritance Basics
The Inheritance SetupInheriting MethodsExtending the ConstructorAdding Child MethodsShared vs UniqueRecap - Shape Hierarchy