Is there a Julian way to combine types generically or a design pattern that achieves the goal?

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.

5 Likes