You don’t have to re-define all the methods accepting a Person
object if you write those methods using functions instead of field access. You just have to define some basic functions
Changing your original example:
abstract type AbstractPerson end
# basic methods to define: name,age,set_age
#basic AbstractPerson
mutable struct Person <: AbstractPerson
name::String
age::Int
end
# CONSTRUCTOR
function Person(name)
return Person(name, 0)
end
#basic methods
name(a::Person) = a.name
age(a::Person) = a.age
set_age(a::Person,x::Integer) = (a.age = x; x)
# TYPE METHODS: always use `AbstractPerson` as input type...
import Base.display
function display(p::AbstractPerson)
println("Person: ", name(p), " (age: ", age(p), ")")
end
function happybirthday(p::AbstractPerson)
set_age(p, age(p) + 1)
println(name(p), " is now ", age(p), " year(s) old")
end
function call(p::AbstractPerson)
print_with_color(:red, uppercase(name(p)), "!")
end
#---------------------------------------------------------------------
# DERIVED TYPE : Citizen
# Use abstract type for the interface name, by convention prepend
# `Abstract` to the type name.
abstract type AbstractCitizen <: AbstractPerson end
# here you should think of basic methods for a AbstrctCitizen, such as nationality(c::AbstractCitizen).
# TYPE MEMBERS (composition of `Person` fields and new ones)
mutable struct Citizen <: AbstractCitizen
person::Person
nationality::String # new field (not present in Person)
end
#now would be a good time to use macros...
name(c::Citizen) = name(c.person)
age(c::Citizen) = age(c.person)
set_age(c::Citizen,x::Int) = set_age(c.person, x)
#basic abstractcitizen method
nationality(c::Citizen) = c.nationality
#Now everything defined for AbstractPerson should work for Citizen
#And you are not tied to field names anymore:
struct EternalBeing <: AbstractPerson end
name(e::EternalBeing) = "The One who Is"
age(e::EternalBeing) = typemax(Int)
set_age(e::EternalBeing,x) = nothing
const eternal = EternalBeing()
# All just work
display(eternal)
happybirthday(eternal)
call(eternal)