liveBook · Manning

Subtyping

As explained in Julia as a Second Language

A subtype is a type whose values are also accepted wherever values of a more general supertype are expected.

Subtyping answers a practical question: can a value be used where a particular type is required? A value’s type must be a subtype of the allowed type. An array with element type Any can hold a string, but an array with element type Integer cannot. Related types are not necessarily interchangeable: Float64 is not a subtype of Integer. section 7.2

Check a relationship

Julia’s <: operator tests subtyping: Int8 <: Integer evaluates to true, while Float64 <: Integer evaluates to false. Use subtypes(Integer) to inspect types immediately below Integer, or repeatedly call supertype to follow a type toward Any. section 7.2

The same <: operator declares a subtype. In a battle simulation, abstract type Warrior end establishes a shared supertype, and mutable struct Archer <: Warrior defines a concrete type whose objects can be created. Abstract types cannot be instantiated or have fields; concrete types can have fields but cannot be subtypes of other concrete types. Giving every warrior a name and health field is a convention, not a requirement enforced by Warrior. section 7.3.1

Listing 7.5 Definition of types in battle simulator
abstract type Warrior end           #1
 
mutable struct Archer <: Warrior    #2
    name::String
    health::Int
    arrows::Int
end
 
mutable struct Pikeman <: Warrior
    name::String
    health::Int
end
 
mutable struct Knight <: Warrior
    name::String
    health::Int
    mounted::Bool                   #3
 end

The declarations show three concrete warrior types sharing an abstract supertype while keeping different fields. section 7.3.1

That shared supertype supports multiple dispatch. A method declared as battle!(a::Warrior, b::Warrior) accepts an Archer and a Knight because both are Warrior subtypes. Inside it, a call to attack! can select a method using the arguments’ concrete types at runtime. section 7.4.2

Subtyping also applies to union types: String and Int64 are each subtypes of Union{Int64, String}, but Float64 is not. A field typed Union{Wagon, Nothing} can therefore hold another wagon or nothing, providing a way to end a chain. section 10.2.2

How Julia as a Second Language covers it

How deep it goes
Works through subtype tests, hierarchy inspection, declarations, and dispatch without developing a formal type-system account.
Examples
Tests numeric subtype relationships, defines warrior variants, and uses a union-typed field to terminate a wagon chain.
What it assumes
Introduces abstract and concrete types through examples while using basic Julia REPL, struct, and function syntax.
What you can do after
Build it from scratch: define an abstract supertype and concrete subtypes, then write methods accepting the shared type.
How it connects
Connects abstract types and concrete types to multiple dispatch and union types.

Also explained in

Compare how 4 books explain subtyping →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Julia as a Second Language. The section links point to the parts of the book it draws on.