Constructors
Prerequisites: Structs
The automatic constructor takes one argument per field. You can add your own constructors — outer constructors are just extra methods:
struct Color
r::UInt8
g::UInt8
b::UInt8
end
Color(gray::Integer) = Color(gray, gray, gray)
function Color(hex::AbstractString)
h = lstrip(hex, '#')
return Color(parse(UInt8, h[1:2], base = 16),
parse(UInt8, h[3:4], base = 16),
parse(UInt8, h[5:6], base = 16))
end
println(Color(10, 20, 30))
println(Color(128))
println(Color("#ff8800"))
Color(0x0a, 0x14, 0x1e)
Color(0x80, 0x80, 0x80)
Color(0xff, 0x88, 0x00)
Try the hex to RGB converter to check colors like these.
Inner constructors enforce rules
An inner constructor is defined inside the struct and replaces the automatic one. Use it to validate data, so an invalid object can never exist:
struct Percentage
value::Float64
function Percentage(v)
0 <= v <= 100 || throw(DomainError(v, "must be between 0 and 100"))
return new(v)
end
end
println(Percentage(42).value)
try
Percentage(120)
catch err
println(sprint(showerror, err))
end
42.0
DomainError with 120:
must be between 0 and 100
Inside an inner constructor, new(...) creates the object.
Keyword constructors with @kwdef
For structs with many fields, Base.@kwdef generates a keyword-argument
constructor with defaults:
Base.@kwdef struct Config
host::String = "localhost"
port::Int = 8080
debug::Bool = false
end
println(Config())
println(Config(port = 3000, debug = true))
Config("localhost", 8080, false)
Config("localhost", 3000, true)
Practice
Write a Fraction struct with integer num and den whose inner
constructor rejects a zero denominator and reduces the fraction with
gcd, so Fraction(6, 8) stores 3/4.
Show solution
struct Fraction
num::Int
den::Int
function Fraction(n, d)
d == 0 && throw(ArgumentError("denominator is zero"))
g = gcd(n, d) * sign(d)
return new(n ÷ g, d ÷ g)
end
end
Base.show(io::IO, f::Fraction) = print(io, f.num, "/", f.den)
println(Fraction(6, 8), " ", Fraction(3, -9))
3/4 -1/3
(Julia already has exact fractions built in — 6 // 8 — but writing
your own is good practice.)