Declare a non-instantiable node with abstract type Animal end. Concrete structs hang under it with struct Dog <: Animal; name::String; end. You never construct Animal() — only leaves.
Julia Medium · Lesson 1 · On the house
Abstract types and hierarchies
abstract type, subtypes, Union{}, and dispatch on the tree. Lesson 1 is free — on the house.
Lessons · Julia Medium · Lesson 1 of 10 · On the house
Abstract types and hierarchies
abstract type, subtypes, Union{}, and dispatch on the tree.

supertype(Dog) and subtypes(Animal) walk the tree. Dog <: Animal is true; Animal <: Dog is false. Field types and method signatures should name the most general type that still keeps your contracts.
Union{Int, Nothing} (often aliased) is a type that accepts either member. Prefer a small Union over Any when the set of cases is closed. Nothing is the singleton for absence; missing is for statistical missingness — different types.
Dispatch sees the runtime type. A method speak(::Animal) is a fallback; speak(::Dog) wins for dogs because it is more specific. Abstract parents organize interfaces; concrete leaves carry data.
Misses: trying to Animal() construct an abstract type, writing Java-style extends instead of <:, or treating Union{} (empty union, bottom) as a bag of values.
abstract-hierarchy
abstract type Animal end
struct Dog <: Animal
name::String
end
struct Cat <: Animal
name::String
end
speak(::Dog) = "woof"
speak(::Cat) = "meow"
speak(::Animal) = "..."
MaybeInt = Union{Int, Nothing}
println(speak(Dog("Rex")))
println(Dog <: Animal)
println(3 isa MaybeInt)
println(nothing isa MaybeInt)
Quiz
Can you construct Animal() after abstract type Animal end?
Quiz
What does Dog <: Animal mean?
Quiz
What values does Union{Int, Nothing} accept?
Quiz
For speak(::Dog) and speak(::Animal), which runs for Dog("Rex")?
Check
Match the still for: Abstract types and hierarchies.
Open-book: the answers are on this page. Pass every quiz and check (5) to mark the lesson done. This visit: 0/5.