Interfaces & conditionals
Last updated on 2023-09-15 | Edit this page
Estimated time: 60 minutes
Overview
Questions
- “How to use conditionals?”
- “What is an interface?”
Objectives
Conditionals
Before starting to work in a new document, Melissa has to:
Activate her environment
  Activating project at `~/projects/trebuchet`
Importing the package under its modified name
Defining the structures
JULIA
mutable struct Trebuchet <: AbstractVector{Float64}
  counterweight::Float64
  release_angle::Float64
end
struct Environment
  wind::Float64
  target_distance::Float64
end
Base.size(::Trebuchet) = tuple(2)Now that Melissa knows that she has to add a method for
getindex(trebuchet::Trebuchet, i::Int)she thinks about the implementation.
If the index is 1 she wants to get the
counterweight field and if the index is 2 she
wants to get release_angle and since these are the only two
fields she wants to return an error if anything else comes in. In Julia
the keywords to specify conditions are if,
elseif and else, closed with an
end. Thus she writes
JULIA
function Base.getindex(trebuchet::Trebuchet, i::Int)
    if i === 1
        return trebuchet.counterweight
    elseif i === 2
        return trebuchet.release_angle
    else
        error("Trebuchet only accepts indices 1 and 2, yours is $i")
    end
endAnd tries again:
OUTPUT
2-element Trebuchet:
 500.0
   0.7853981633974483Notice, that the printing is different from our
trebuchet in the former
episode.
Interfaces
Why is that? By subtyping Trebuchet as
AbstractVector we implicitly opted into a widespread
interface in the Julia language: AbstractArrays.
An interface is a collection of methods that should be implemented by
all subtypes of the interface type in order for generic code to work.
For example, the Julia
manual lists all methods that a subtype of
AbstractArray need to implement to adhere to the
AbstractArray interface:
- 
size(A)returns a tuple containing the dimensions ofA
- 
getindex(A, i::Int)returns the value associated with indexi
- 
setindex!(A, v, i::Int)writes a new valuevat the indexi(optional)
Now, that Melissa implemented the mandatory methods for this
interface for the Trebuchet type, it will work with every
function in Base that accepts an
AbstractArray. She tries a few things that now work without
her writing explicit code for it:
OUTPUT
2-element Vector{Float64}:
 1000.0
    1.5707963267948966OUTPUT
250000.61685027508OUTPUT
2×2 Matrix{Float64}:
 250000.0    392.699
    392.699    0.61685That is, it now behaves like you would expect from an ordinary matrix.
Now she goes about implementing the missing optional method for
setindex! of the AbstractArray interface.
Implement setindex!
Write the missing method for
setindex(trebuchet::Trebuchet, v, i::Int) similar to
Melissas getindex function.
With the new Trebuchet defined with a complete
AbstractArray interface, Melissa tries her new method to
modify a counterweight by index:
OUTPUT
2OUTPUT
2-element Trebuchet:
 2.0
 0.7853981633974483Keypoints
- “Interfaces are informal”
- “Interfaces facilitate code reuse”
- “Conditions use if,elseif,elseandend”