Perhaps you saw this in one of the linked threads and didn’t find it a good solution for some other reason, but FWIW in this case I would just do:
type Person # ...
name(p::Person) = p.name
setname!(p::Person, name) = (p.name = name)
greet(p::Person) = println("Hello, $(name(p))")
type PersonAndAddress
person::Person
# ...
@forward PersonAndAddress.person name, setname!, greet
type Employee # ...
@forward Employee.person_and_address name, setname!, greet
@forward Employee.seniority_level seniority, setseniority! # etc
@forward
isn’t doing anything particularly crazy or magical here, just defining the set of methods like greet(p::PersonAndAddress, args...) = greet(p.person, args...)
. I’ve been pretty happy with this solution and haven’t found a great need for anything fancier, but if you were really working with a lot of functions you could easily generalise this to groups, e.g. (heavily cut down for brevity)
personprotocol = [name, setname!, greet]
@forward Employee.person_and_address personprotocol
employeeprotocol = [personprotocol, fire!]
@forward SeniorEmployee.employee employeeprotocol
I think that would would be enough to make your example – and more extreme versions of it – manageable, but let me know if that’s not the case.