0
0
Swiftprogramming~15 mins

Why inheritance is class-only in Swift - Why It Works This Way

Choose your learning style9 modes available
Overview - Why inheritance is class-only in Swift
What is it?
Inheritance in Swift means one type can take properties and behaviors from another. However, only classes can inherit from other classes. Structures and enumerations cannot inherit. This design choice helps keep Swift safe and clear about how data and behavior are shared.
Why it matters
Without limiting inheritance to classes, Swift would risk confusing how data is copied and shared. If structs or enums inherited, it could cause unexpected bugs or performance issues. This rule helps developers write safer, more predictable code, especially when working with complex data.
Where it fits
Before this, learners should understand basic Swift types: classes, structs, and enums. After this, they can explore protocols and protocol inheritance, which provide flexible ways to share behavior without class inheritance.
Mental Model
Core Idea
Inheritance is limited to classes in Swift because only classes have shared, reference-based identity that inheritance relies on.
Think of it like...
Inheritance in Swift is like a family heirloom passed down only through a family line (classes), while structs and enums are like individual souvenirs that don’t get passed down but copied instead.
┌─────────────┐       inherits       ┌─────────────┐
│   Class A   │────────────────────▶│   Class B   │
└─────────────┘                     └─────────────┘

Structures and enums:

┌─────────────┐  copy  ┌─────────────┐
│  Struct A   │──────▶│  Struct B   │
└─────────────┘       └─────────────┘
Build-Up - 6 Steps
1
FoundationUnderstanding Swift Types
🤔
Concept: Introduce the three main Swift types: classes, structs, and enums, and their basic differences.
Swift has three main ways to create custom data types: classes, structs, and enums. Classes are reference types, meaning they share a single copy when assigned or passed around. Structs and enums are value types, meaning they get copied when assigned or passed.
Result
Learners can distinguish between reference and value types in Swift.
Understanding the difference between reference and value types is key to grasping why inheritance is limited to classes.
2
FoundationWhat is Inheritance in Swift?
🤔
Concept: Explain inheritance as a way for one class to reuse code from another class.
Inheritance lets a class take properties and methods from another class. The class that inherits is called a subclass, and the one it inherits from is the superclass. This helps avoid repeating code and allows behavior to be shared.
Result
Learners understand the basic purpose and use of inheritance in Swift classes.
Knowing inheritance is about sharing behavior helps see why it fits naturally with reference types.
3
IntermediateWhy Structs and Enums Can't Inherit
🤔Before reading on: do you think structs and enums could safely inherit behavior like classes? Commit to your answer.
Concept: Explain why value types like structs and enums do not support inheritance.
Structs and enums are copied when assigned or passed, so they don’t share identity. Inheritance relies on shared identity to override or extend behavior. Allowing inheritance for value types would break this model and cause confusing behavior.
Result
Learners see the technical reason why inheritance is class-only in Swift.
Understanding that inheritance depends on shared identity clarifies why value types can’t inherit.
4
IntermediateProtocols as an Alternative to Inheritance
🤔Before reading on: do you think protocols can replace inheritance for structs and enums? Commit to your answer.
Concept: Introduce protocols as a way to share behavior without inheritance.
Protocols define methods and properties that types can adopt. Unlike inheritance, protocols work with classes, structs, and enums. This lets value types share behavior safely without inheritance’s risks.
Result
Learners understand how Swift uses protocols to provide flexibility beyond class inheritance.
Knowing protocols fill the gap left by no inheritance for value types helps understand Swift’s design balance.
5
AdvancedReference Semantics and Identity in Classes
🤔Before reading on: do you think identity is important for inheritance to work? Commit to your answer.
Concept: Explain how classes have identity and reference semantics that inheritance depends on.
Classes are reference types, meaning multiple variables can point to the same instance. This shared identity allows subclasses to override behavior and maintain consistent state. Value types lack this shared identity, so inheritance would not behave as expected.
Result
Learners grasp the deep connection between reference semantics and inheritance.
Understanding identity as the foundation of inheritance prevents confusion about why value types can’t inherit.
6
ExpertPerformance and Safety Tradeoffs in Swift’s Design
🤔Before reading on: do you think allowing inheritance for value types would improve or harm Swift’s safety and performance? Commit to your answer.
Concept: Explore the design tradeoffs Swift made to keep value types safe and efficient by restricting inheritance.
Allowing inheritance for value types would complicate copying and mutation semantics, potentially causing bugs and performance hits. Swift’s choice to keep inheritance class-only preserves value types’ simplicity and efficiency, while protocols provide flexible behavior sharing.
Result
Learners appreciate the careful balance Swift strikes between power, safety, and performance.
Knowing the tradeoffs behind this design helps understand Swift’s unique approach and guides better coding decisions.
Under the Hood
Inheritance works by creating a class hierarchy where subclasses hold a reference to a shared instance in memory. This allows method overriding and shared state. Structs and enums are copied on assignment, so each copy is independent. This copying breaks the shared identity inheritance needs, so the compiler disallows inheritance for value types.
Why designed this way?
Swift was designed to combine safety, performance, and clarity. Restricting inheritance to classes avoids complex and error-prone behaviors with value types. Instead, Swift uses protocols to share behavior flexibly without inheritance’s pitfalls. This design reduces bugs and improves code predictability.
┌───────────────┐
│   Class A     │
│  (reference)  │
└──────┬────────┘
       │ inherits
┌──────▼────────┐
│   Class B     │
│  (reference)  │
└───────────────┘

Value types copy on assignment:

┌───────────────┐     copy     ┌───────────────┐
│   Struct A    │────────────▶│   Struct B    │
│  (value type) │             │  (value type) │
└───────────────┘             └───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Can structs inherit from other structs in Swift? Commit to yes or no.
Common Belief:Structs can inherit from other structs just like classes do.
Tap to reveal reality
Reality:Structs cannot inherit from other structs; inheritance is only for classes.
Why it matters:Believing structs can inherit leads to confusion and attempts to use unsupported features, causing compile errors.
Quick: Does inheritance mean copying data in Swift? Commit to yes or no.
Common Belief:Inheritance copies data from one type to another.
Tap to reveal reality
Reality:Inheritance shares behavior and identity via references; it does not copy data like value types do.
Why it matters:Misunderstanding this causes confusion about how changes affect instances and can lead to bugs.
Quick: Can protocols replace all uses of inheritance in Swift? Commit to yes or no.
Common Belief:Protocols are just like inheritance and can do everything inheritance does.
Tap to reveal reality
Reality:Protocols provide behavior sharing but lack identity and state inheritance that classes have.
Why it matters:Thinking protocols fully replace inheritance can cause design mistakes when identity or shared state is needed.
Quick: Is inheritance allowed for enums in Swift? Commit to yes or no.
Common Belief:Enums can inherit from other enums or classes.
Tap to reveal reality
Reality:Enums cannot inherit from any type; they are value types without inheritance.
Why it matters:Expecting inheritance for enums leads to confusion and wasted time trying unsupported patterns.
Expert Zone
1
Inheritance relies on reference semantics, so even subtle changes in class identity affect behavior in ways protocols cannot replicate.
2
Swift’s use of protocols with extensions provides a powerful alternative to inheritance, enabling code reuse without the risks of shared mutable state.
3
The compiler enforces inheritance rules strictly to prevent subtle bugs that arise from mixing value and reference semantics.
When NOT to use
Inheritance should not be used when you need value semantics or want to avoid shared mutable state. Instead, use structs or enums with protocols and protocol extensions for behavior sharing. Also, avoid inheritance when composition or delegation patterns better fit the design.
Production Patterns
In production Swift code, inheritance is typically used for UI classes (like UIViewController) or model objects requiring shared identity. Protocols and value types dominate business logic and data structures to ensure safety and performance. This separation helps maintain clear, maintainable codebases.
Connections
Protocols in Swift
Protocols provide behavior sharing without inheritance, complementing class-only inheritance.
Understanding protocols helps grasp how Swift balances flexibility and safety by separating behavior sharing from identity inheritance.
Reference vs Value Semantics
Inheritance depends on reference semantics, which contrasts with value semantics used by structs and enums.
Knowing the difference between reference and value semantics clarifies why inheritance is limited to classes.
Object-Oriented Programming (OOP)
Inheritance is a core OOP concept, but Swift modifies it by restricting it to classes for safety.
Seeing how Swift adapts OOP principles helps understand modern language design tradeoffs.
Common Pitfalls
#1Trying to inherit from a struct or enum causes errors.
Wrong approach:struct MyStruct: AnotherStruct { }
Correct approach:Use protocols instead: protocol MyProtocol { } struct MyStruct: MyProtocol { }
Root cause:Misunderstanding that only classes support inheritance in Swift.
#2Assuming inheritance copies data like value types.
Wrong approach:class A { var x = 1 } class B: A { } let b = B() b.x = 2 // Expecting A's x to remain 1
Correct approach:Understand that b and any reference to the same instance share x, so changes affect all references.
Root cause:Confusing reference semantics with value copying.
#3Using inheritance to share behavior when composition is better.
Wrong approach:class Animal { func sound() {} } class Dog: Animal { override func sound() { print("Bark") } } // Overusing inheritance for unrelated behaviors
Correct approach:Use protocols and composition: protocol SoundMaking { func sound() } struct Dog: SoundMaking { func sound() { print("Bark") } }
Root cause:Not recognizing when inheritance leads to rigid, fragile designs.
Key Takeaways
Inheritance in Swift is limited to classes because only classes have shared reference identity needed for inheritance to work.
Structs and enums are value types that copy data, so they cannot safely support inheritance.
Protocols provide a flexible way to share behavior across all types without inheritance’s risks.
Understanding reference versus value semantics is essential to mastering Swift’s type system and inheritance rules.
Swift’s design balances safety, performance, and flexibility by restricting inheritance and promoting protocols.