09: Inheritance and Mixins
Audience: All Time: 120 minutes Prerequisites: 07-Classes, 08-Interfaces You'll learn: Extend classes, override methods, super calls, mixins, hierarchies
The Big Picture
Inheritance lets classes extend other classes, sharing code and building hierarchies. Instead of duplicating code, parent classes provide common functionality that children specialize.
Animal (parent)
├── Dog (specializes in dogs) ├── Cat (specializes in cats) └── Bird (specializes in birds)
Basic Inheritance
Extending a Class
// file: 09_inheritance_basic.zbr
// teaches: class inheritance // chapter: 09-Inheritance-and-Mixins
class Animal var name as str = "" var age as int = 0
def greet print "I'm ${name}, ${age} years old"
class Dog inherits Animal def bark print "${name} says: Woof!"
class Cat inherits Animal def meow print "${name} says: Meow!"
class Main shared def main var dog = Dog() dog.name = "Buddy" dog.age = 3 dog.greet() // I'm Buddy, 3 years old dog.bark() // Buddy says: Woof!
var cat = Cat() cat.name = "Whiskers" cat.age = 2 cat.greet() // I'm Whiskers, 2 years old cat.meow() // Whiskers says: Meow!
Key points: - inherits Animal — Dog extends Animal - Inherits fields (name, age) and methods (greet) - Can add new methods (bark, meow)
Method Overriding
// file: 09_override.zbr
// teaches: overriding parent methods // chapter: 09-Inheritance-and-Mixins
class Animal def speak as str return "Some sound"
class Dog inherits Animal def speak as str // Override parent method return "Woof!"
class Cat inherits Animal def speak as str // Different implementation return "Meow!"
class Main shared def main var dog = Dog() print dog.speak() // Woof!
var cat = Cat() print cat.speak() // Meow!
Super Calls (Calling Parent Methods)
// file: 09_super.zbr
// teaches: calling parent implementation // chapter: 09-Inheritance-and-Mixins
class Vehicle var speed as int = 0
def accelerate speed = speed + 10 print "Accelerating to ${speed} mph"
class Car inherits Vehicle def accelerate // Override but call parent # First call parent implementation super.accelerate() # Then add custom behavior print "Car is now cruising smoothly"
class Main shared def main var car = Car() car.accelerate() // Accelerating to 10 mph // Car is now cruising smoothly
Hierarchies
Multi-Level Inheritance
// file: 09_hierarchy.zbr
// teaches: inheritance hierarchies // chapter: 09-Inheritance-and-Mixins
class Animal var name as str = "" def sound as str return "?"
class Mammal inherits Animal def warm_blooded as bool return true
class Dog inherits Mammal def sound as str return "Woof!"
class Main shared def main var dog = Dog() dog.name = "Buddy" print dog.name // Buddy print dog.sound() // Woof! print dog.warm_blooded() // true
Treating as Parent Type
// file: 09_polymorphic_hierarchy.zbr
// teaches: treating children as parents // chapter: 09-Inheritance-and-Mixins
class AnimalShelter var animals as List(Animal) = List()
def add_animal(animal as Animal) animals.add(animal)
def announce_arrivals for animal in animals print "We have ${animal.name}" print "It says: ${animal.sound()}"
class Main shared def main var shelter = AnimalShelter()
var dog = Dog() dog.name = "Rex" shelter.add_animal(dog)
var cat = Cat() cat.name = "Mittens" shelter.add_animal(cat)
shelter.announce_arrivals()
Mixins
Mixins let you compose behavior from multiple sources without deep inheritance chains.
// file: 09_mixins.zbr
// teaches: mixin composition // chapter: 09-Inheritance-and-Mixins
class Swimmer def swim print "Swimming!"
class Runner def run print "Running!"
class Duck inherits Swimmer var name as str = ""
def quack print "${name} quacks!"
class Dog inherits Swimmer var name as str = "" def bark print "${name} barks!"
class Athlete inherits Runner var name as str = "" def compete run() print "${name} is competing!"
class Main shared def main var duck = Duck() duck.name = "Donald" duck.swim() // Swimming! duck.quack() // Donald quacks!
var dog = Dog() dog.name = "Buddy" dog.swim() // Swimming! dog.bark() // Buddy barks!
var athlete = Athlete() athlete.name = "Alice" athlete.compete() // Running! Alice is competing!
Real World: Document Hierarchy
// file: 09_document_hierarchy.zbr
// teaches: realistic inheritance use // chapter: 09-Inheritance-and-Mixins
class Document var title as str = "" var content as str = "" var created_at as str = ""
def preview as str var lines = content.split("\n") if lines.count() > 3 return lines.at(0).concat("\n").concat(lines.at(1)).concat("\n").concat(lines.at(2)) return content
class BlogPost inherits Document var author as str = "" var tags as List(str) = List()
def get_summary as str return "Posted by ${author}: ${preview()}"
class Report inherits Document var department as str = "" var sections as List(str) = List()
def is_complete as bool return sections.count() > 0
class Main shared def main var post = BlogPost() post.title = "Learning Zebra" post.content = "Zebra is awesome\nLine 2\nLine 3\nLine 4" post.author = "Alice" post.tags.add("programming") print post.get_summary()
var report = Report() report.title = "Q1 Report" report.department = "Engineering" report.sections.add("Achievements") report.sections.add("Challenges") print "Report complete: ${report.is_complete()}"
Common Patterns
Template Method Pattern
class DataProcessor
def process(data as str) var cleaned = clean(data) var transformed = transform(cleaned) var validated = validate(transformed) return validated
def clean(data as str) as str return data.trim()
def transform(data as str) as str return data.upper()
def validate(data as str) as bool return data.len > 0
class CustomProcessor inherits DataProcessor def transform(data as str) as str return data.lower() // Override just this step
Factory Pattern
class AnimalFactory
shared def create(kind as str) as Animal if kind == "dog" return Dog() elif kind == "cat" return Cat() else return Animal()
If you're new to programming
> Inheritance is like saying "Dog is a type of Animal." Dogs have everything animals have, plus their own special abilities. > > Override means giving your own version of a method. Even though Animal has a speak method, Dog can have its own version that says "Woof!" > > Super is saying "run the parent's version first, then my custom version."
Common Mistakes
> ❌ Mistake: Forgetting to call super > >
> class Car > inherits Vehicle > def accelerate > print "Car accelerating" // ❌ Forgot super.accelerate() > > > ✅ Better: > > class Car > inherits Vehicle > def accelerate > super.accelerate() // ✅ Call parent first > print "Car accelerating" >
> ❌ Mistake: Deep inheritance chains > >
> class A; inherits B > class B; inherits C > class C; inherits D > class D; inherits E # ❌ Too deep, hard to understand > > > ✅ Better: Keep hierarchies shallow (2-3 levels max), use composition/mixins for complex behavior
> ❌ Mistake: Overriding with wrong signature > >
> class Animal > def speak as str > > class Dog > inherits Animal > def speak(volume as int) as str # ❌ Wrong signature > > > ✅ Better: > > class Dog > inherits Animal > def speak as str # ✅ Same signature > return "Woof!" >
Exercises
Exercise 1: Vehicle Hierarchy
Create a vehicle hierarchy with cars, motorcycles, and trucks:
Solution
class Vehicle
var brand as str = "" var year as int = 0
def start_engine print "Starting engine"
def info as str return "${year} ${brand}"
class Car inherits Vehicle var doors as int = 4
def start_engine super.start_engine() print "Car engine started"
class Motorcycle inherits Vehicle def start_engine super.start_engine() print "Motorcycle engine roared to life"
class Main shared def main var car = Car() car.brand = "Toyota" car.year = 2023 print car.info() // 2023 Toyota car.start_engine() // Starting engine / Car engine started
var bike = Motorcycle() bike.brand = "Harley" bike.year = 2022 bike.start_engine() // Starting engine / Motorcycle engine roared to life
Exercise 2: Employee Hierarchy
Create an employee hierarchy (Employee → Manager → Director):
Solution
class Employee
var name as str = "" var salary as float = 0.0
def get_info as str return "${name}: ${salary}"
class Manager inherits Employee var team_size as int = 0
def get_info as str return super.get_info().concat(" (Managing ${team_size} people)")
class Director inherits Manager var budget as float = 0.0
def get_info as str return super.get_info().concat(" (Budget: ${budget})")
class Main shared def main var emp = Employee() emp.name = "Alice" emp.salary = 50000.0 print emp.get_info()
var mgr = Manager() mgr.name = "Bob" mgr.salary = 70000.0 mgr.team_size = 5 print mgr.get_info()
var dir = Director() dir.name = "Carol" dir.salary = 100000.0 dir.team_size = 20 dir.budget = 1000000.0 print dir.get_info()
Exercise 3: Shape Hierarchy
Extend the shape interface from Chapter 08 with inheritance:
Solution
interface Shape
def area as float def perimeter as float
class BaseShape implements Shape def area as float return 0.0 def perimeter as float return 0.0
class Circle inherits BaseShape var radius as float = 0.0
def area as float return 3.14 radius radius
def perimeter as float return 2.0 3.14 radius
class Rectangle inherits BaseShape var width as float = 0.0 var height as float = 0.0
def area as float return width * height
def perimeter as float return 2.0 * (width + height)
class Main shared def main var shapes as List(Shape) = List()
var circle = Circle() circle.radius = 5.0 shapes.add(circle)
var rect = Rectangle() rect.width = 10.0 rect.height = 5.0 shapes.add(rect)
for shape in shapes print "Area: ${shape.area()}"
Next Steps
- → 10-Properties — Getters, setters, computed values - → 14-Contracts — Enforce invariants across hierarchies - 🏋️ Project-1-CLI-Tool — Use hierarchies for options/commands
Key Takeaways
- Inheritance creates hierarchies — Specialize parent classes - Override methods to customize behavior in child classes - Super calls let you extend parent functionality - Keep hierarchies shallow — 2-3 levels is healthy - Treat as parent type for polymorphism - Mixins compose behavior without deep chains
Next: Head to 10-Properties to control field access with getters and setters.