liveBook · Manning

Interface

As explained in Julia as a Second Language

An interface is a defined set of operations and behavioral expectations through which software components interact independently of their implementations.

An interface is a shared way to use different implementations. A mouse and keyboard let you operate different computers without knowing their hardware; likewise, code can use arrays and ranges without caring how each stores its elements. Both support indexing and iteration, even though a range’s elements are implicit. section 12.1

One function, two array implementations

In Julia, `function addup(xs::AbstractArray); total = 0; for x in xs; total += x; end; total; end` returns `12` for both `addup(3:5)` and `addup([3, 4, 5])`. It rejects `addup((3, 4, 5))`: a tuple is not an `AbstractArray`. That restriction belongs to `addup`, not to addition in general—`sum((3, 4, 5))` works. section 12.1

Julia interfaces are informal: there is no special interface declaration. Define functions and document which methods another type must provide. Methods belong to functions rather than types, so an abstract type alone does not tell an implementer every required operation. section 12.2

Make a tank contract discoverable

Suppose `refill!(tank::Tank)` calls `totalmass(tank)` and `drymass(tank)`. A new `Tank` subtype can have fields with those names yet still lack the required methods. With no `totalmass` function defined, refilling produces `UndefVarError`; defining the documented generic function changes the missing-implementation failure to a `MethodError`. Documenting `totalmass(t::Tank) -> Float64` tells implementers what to supply. section 12.2

An interface can also supply some behavior. For a `Cipher`, character-level `encrypt` and `decrypt` methods can be required while string-level methods map those operations over characters. Explicit fallback errors can tell developers what to implement. A password service holding an abstract `Cipher` can then use either a Caesar cipher or a substitution cipher without changing its own encryption calls. section 15.6

Listing 15.10 Defining an abstract cipher interface
abstract type Cipher end

function encrypt(cipher::Cipher, char::Char)
   error("Implement encrypt(::", typeof(cipher), ", char)")
end

function decrypt(cipher::Cipher, char::Char)
   error("Implement decrypt(::", typeof(cipher), ", char)")
end

function encrypt(cipher::Cipher, message::AbstractString)
   map(ch -> encrypt(cipher, ch), message)
end
function decrypt(cipher::Cipher, ciphertext::AbstractString)
   map(ch -> decrypt(cipher, ch), ciphertext)
end

The cipher listing shows the distinction between character methods that signal a missing implementation and string methods that reuse them through `map`. section 15.6

The same payoff applies to collections: make a custom structure such as a staged rocket iterable, and functions including `map`, `reduce`, `filter`, `sum`, and `collect` become available to it. section 12.0 section 12.7

How Julia as a Second Language covers it

How deep it goes
Explains Julia’s informal, documented method contracts through failures, defaults, and working implementations; does not introduce interface-declaration syntax.
Examples
Uses array–range summation, a propellant tank’s missing methods, interchangeable ciphers, and an iterable staged rocket.
What it assumes
Assumes familiarity with Julia functions, types, and loops while explaining the informal interface convention explicitly.
What you can do after
Build it from scratch by documenting required methods, implementing them for concrete types, and reusing functions across implementations.
How it connects
Connects interfaces to abstract types, multiple dispatch, iteration, collections, and default methods.

Also explained in

Compare how 7 books explain interface →

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.