Julia Interfaces Tutorial

A Julia tutorial covering interfaces with practical examples and explanations.

Julia Interfaces Tutorial

Julia Interfaces Tutorial

last modified March 3, 2025

In Julia, interfaces are informal contracts that define a set of methods a type must implement to satisfy a particular behavior. Unlike other languages, Julia does not enforce interfaces explicitly. Instead, they are conventions.

Interfaces are crucial for polymorphism, allowing different types to be used interchangeably if they implement the required methods.

Iteration Interface

The iteration interface requires implementing iterate and Base.IteratorSize.

main.jl

struct MyRange start::Int stop::Int end

Base.iterate(r::MyRange, state=r.start) = state > r.stop ? nothing : (state, state + 1) Base.IteratorSize(::Type{MyRange}) = Base.HasLength()

This example defines a custom range type that supports iteration.

Indexing Interface

The indexing interface requires implementing getindex and setindex!.

main.jl

struct MyArray data::Vector{Int} end

Base.getindex(a::MyArray, i::Int) = a.data[i] Base.setindex!(a::MyArray, v::Int, i::Int) = a.data[i] = v

This example defines a custom array type that supports indexing.

AbstractArray Interface

The AbstractArray interface requires implementing methods like size and getindex.

main.jl

struct MyMatrix data::Matrix{Int} end

Base.size(m::MyMatrix) = size(m.data) Base.getindex(m::MyMatrix, i::Int, j::Int) = m.data[i, j]

This example defines a custom matrix type that behaves like an array.

AbstractFloat Interface

The AbstractFloat interface requires implementing methods like +, -, and *.

main.jl

struct MyFloat value::Float64 end

Base.:+(a::MyFloat, b::MyFloat) = MyFloat(a.value + b.value) Base.:-(a::MyFloat, b::MyFloat) = MyFloat(a.value - b.value) Base.:*(a::MyFloat, b::MyFloat) = MyFloat(a.value * b.value)

This example defines a custom floating-point type with arithmetic operations.

AbstractString Interface

The AbstractString interface requires implementing methods like ncodeunits and codeunit.

main.jl

struct MyString data::String end

Base.ncodeunits(s::MyString) = ncodeunits(s.data) Base.codeunit(s::MyString, i::Int) = codeunit(s.data, i)

This example defines a custom string type that behaves like a standard string.

AbstractDict Interface

The AbstractDict interface requires implementing methods like get and haskey.

main.jl

struct MyDict data::Dict{String, Int} end

Base.get(d::MyDict, key::String, default) = get(d.data, key, default) Base.haskey(d::MyDict, key::String) = haskey(d.data, key)

This example defines a custom dictionary type that supports key-value lookups.

AbstractSet Interface

The AbstractSet interface requires implementing methods like in and length.

main.jl

struct MySet data::Set{Int} end

Base.in(x::Int, s::MySet) = x in s.data Base.length(s::MySet) = length(s.data)

This example defines a custom set type that supports membership checks.

AbstractChannel Interface

The AbstractChannel interface requires implementing methods like put! and take!.

main.jl

struct MyChannel data::Channel{Int} end

Base.put!(c::MyChannel, x::Int) = put!(c.data, x) Base.take!(c::MyChannel) = take!(c.data)

This example defines a custom channel type for inter-task communication.

AbstractIO Interface

The AbstractIO interface requires implementing methods like read and write.

main.jl

struct MyIO data::IOBuffer end

Base.read(io::MyIO, n::Int) = read(io.data, n) Base.write(io::MyIO, x::UInt8) = write(io.data, x)

This example defines a custom I/O type for reading and writing data.

AbstractTask Interface

The AbstractTask interface requires implementing methods like schedule and wait.

main.jl

struct MyTask task::Task end

Base.schedule(t::MyTask) = schedule(t.task) Base.wait(t::MyTask) = wait(t.task)

This example defines a custom task type for asynchronous execution.

Best Practices for Interfaces

  • Follow Conventions: Adhere to Julia’s informal interface conventions.

  • Document Behavior: Clearly document expected behavior for custom types.

  • Test Thoroughly: Ensure custom types work with generic functions.

  • Use Abstract Types: Leverage abstract types for flexible design.

Source

Julia Interfaces Documentation

In this tutorial, we explored Julia interfaces with practical examples, covering iteration, indexing, arrays, and more. Interfaces enable flexible and reusable code in Julia.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Julia tutorials.

ad ad