Basic
Here's an example of single-argument interface using animals, and the implementation of a duck.
Definition
First we define the interface methods, and a list of mandatory and optional properties of the interface, with conditions, using the @interface
macro.
The @interface
macro takes three arguments:
- The name of the interface, which should usully end with "Interface"
- The
mandatory
andoptional
components of the interface written as aNamedTuple
, with functions or tuple of functions that test them. - The interface docstring (the interface is represented as a type)
module Animals
using Interfaces
abstract type Animal end
function age end
function walk end
function talk end
function dig end
components = (
mandatory = (
age = (
"all animals have a `Real` age" => x -> age(x) isa Real,
"all animals have an age larger than zero" => x -> age(x) >= 0,
),
),
optional = (
walk = "this animal can walk" => x -> walk(x) isa String,
talk = "this animal can talk" => x -> talk(x) isa Symbol,
dig = "this animal can dig" => x -> dig(x) isa String,
)
)
description = """
Defines a generic interface for animals to do the things they do best.
"""
@interface AnimalInterface Animal components description
end;
Implementation
using Interfaces, Test
Now we implement the AnimalInterface
, for a Duck
.
struct Duck <: Animals.Animal
age::Int
end
Animals.age(duck::Duck) = duck.age
Animals.walk(::Duck) = "waddle"
Animals.talk(::Duck) = :quack
We then test that the interface is correctly implemented
ducks = [Duck(1), Duck(2)]
Interfaces.test(Animals.AnimalInterface, Duck, ducks)
true
As well as two optional methods
Interfaces.test(Animals.AnimalInterface{(:walk,:talk)}, Duck, ducks)
true
Finally we declare it, so that the information can be used in static dispatch.
The @implements
macro takes two arguments.
- The interface type, with a tuple of optional components in its first type parameter.
- The type for which the interface is implemented.
@implements Animals.AnimalInterface{(:walk,:talk)} Duck [Duck(1), Duck(2)]
Now let's see what happens when the interface is not correctly implemented.
struct Chicken <: Animals.Animal end
As expected, the tests fail
chickens = [Chicken()]
try
Interfaces.test(Animals.AnimalInterface, Chicken, chickens)
catch e
print(e)
end
@test Interfaces.test(Duck) == true # Test all implemented interfaces for Duck
@test Interfaces.test(Animals.AnimalInterface) == true # Test all implemented types for AnimalInterface
@test Interfaces.test_objects(Animals.AnimalInterface) == Dict(Duck => ducks)
Test Passed
This page was generated using Literate.jl.