# Method inheritance the Julian way

**URL:** https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198
**Category:** New to Julia
**Tags:** inheritance
**Created:** [August 28, 2021, 12:58am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198 "2021-08-28T00:58:09Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![elenev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elenev/32/18440_2.png) [@elenev](https://discourse.julialang.org/u/elenev)
#### Post date: [August 28, 2021, 12:58am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/1 "2021-08-28T00:58:09Z")

</div>

Suppose I am trying to describe the behavior of a `Pet`. I implemented several methods common to all instances of `Pet` e.g. `eat(pet::Pet)` and `walk(pet::Pet, towards)`. I also want to define

```julia
function greet(pet::Pet, person::Person)
walk(pet,person)
say_hello(pet)
# do some other stuff
end

```

where `say_hello()` depends on whether `Pet` is a `Cat` or a `Dog` e.g.

```julia
say_hello(::Dog) = bark()
say_hello(::Cat) = meow()

```

The key idea is that `greet` performs some action common to all `Pet` instances but also some action that depends on which subtype of `Pet` it is. In the MWE above, `greet` is pretty simple and sequential but in principle it could be more complicated, and `say_hello` could be called in some loop, or be called multiple times, etc. Moreover, I’d like other people to be able to define other kinds of `Pet`’s who `say_hello()` in other ways without my code for `greet()` needing to be aware of that.

In an OOP language, I would implement this as something like this (pseudocode):

```julia
class Pet {
abstract say_hello();
eat() { 
internal_eat(); 
}
walk(towards) { 
internal_walk(); 
}
function greet(towards) {
walk(person)
say_hello(pet)
# do some other stuff
}
}

class Dog extends Pet {
say_hello() {
bark()
}
}

class Cat extends Pet {
say_hello() {
meow()
}
}

```

where `internal_eat()`, `internal_walk()`, `bark()`, and `meow()` are “private” methods of their respectiveclasses.

Now, I can’t do this in Julia, so the best alternative I can think of is:

```julia
struct Pet{F<:Function}
say_hello::F 
end

eat(pet::Pet) = internal_eat(pet)
walk(pet::Pet, person::Person) = internal_walk(pet, person)
function greet(pet::Pet, person::Person)
walk(pet, person)
pet.say_hello()
end

dog = Pet(bark())
cat = Pet(meow())

```

But this looks kind of ugly, is hard to read, doesn’t feel very Julian, and just seems like I’m trying to recreate OOP instead of buying into a different/better paradigm.

How do I think about this problem in a more Julian way?

BTW, if the MWE is too contrived, the problem that inspired it is a class of models that are all solved in the same way, but where the specifics of one step of the solution depend on the specifics of the model – not just parameters but equations, too.

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [August 28, 2021, 1:05am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/2 "2021-08-28T01:05:51Z")

</div>

```julia
julia> abstract type Pet end

julia> function greet(pet::Pet, name)
           print("$(pet.name) $(say_hello(pet))ed $name.")
       end

julia> struct Dog <: Pet
           name::String
       end

julia> say_hello(d::Dog) = "Bark"

julia> greet(Dog("jerry"), "tom")
jerry Barked tom.

julia> struct Cat <: Pet
           name::String
       end

julia> say_hello(d::Cat) = "Meow"
say_hello (generic function with 2 methods)

julia> greet(Cat("mary"), "tom")
mary Meowed tom.

```

something like this? The big picture is that, if `Pet` is not enough to determine what happens (in terms of your abstraction model, `say_hello`), then you shouldn’t be able to have a concrete Pet object, thus it’s an abstract type. Users then just go about implement their own Pet concrete sub types.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [August 28, 2021, 1:05am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/3 "2021-08-28T01:05:58Z")

</div>

Your first code snippet doesn’t do already what you want? (As shown above, there was only a subtyping missing).

---

<div class="post-metadata">

### Author: ![elenev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elenev/32/18440_2.png) [@elenev](https://discourse.julialang.org/u/elenev)
#### Post date: [August 28, 2021, 1:18am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/4 "2021-08-28T01:18:29Z")

</div>

You can’t inherit from concrete types. My MWE was too M, I guess, but there is data that I need to store in `Pet` b/c both, say, `eat` and `greet` rely on that data. So I need `Pet` to be concrete. I guess I can just expect `Dog` and `Cat` to have the appropriately named fields containing the needed data, but there’s no good way to document that or enforce it. So that doesn’t sound great.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [August 28, 2021, 1:22am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/5 "2021-08-28T01:22:13Z")

</div>

You may be interested in traits: [Holy Traits Pattern (book excerpt)](https://ahsmart.com/pub/holy-traits-design-patterns-and-best-practice-book/)

---

<div class="post-metadata">

### Author: ![elenev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elenev/32/18440_2.png) [@elenev](https://discourse.julialang.org/u/elenev)
#### Post date: [August 28, 2021, 1:24am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/6 "2021-08-28T01:24:52Z")

</div>

I suppose I can use functions to obtain the needed data in a subtype-agnostic way.

E.g. instead of

```julia
struct Pet
name::String
end

struct Dog<:Pet
end

```

which is illegal in Julia, the interface for `Pet` can just require that `get_name()` be implemented for all subtypes, so that any functions with `Pet`-type argument that need to know the pet’s name just call `get_name(pet)` and don’t need to know how that name is stored. But if there are a lot of fields like that, I’m asking the developers of `Dog` and `Cat` to write a lot of boilerplate code…

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [August 28, 2021, 1:32am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/7 "2021-08-28T01:32:38Z")

</div>

What about:

```julia
struct Common
   name
end

struct Pet
   common::Common
   sayhello
end

Pet(name::String, sayhello:: String) = Pet(Common(name),sayhello)

name(p::Pet) = p.common.name
sayhello(p::Pet) = p.sayhello

```

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [August 28, 2021, 1:37am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/8 "2021-08-28T01:37:54Z")

</div>

> [@elenev](#):
>
> but there’s no good way to document that or enforce it. So that doesn’t sound great.

duck typing is common in Class-Based OOP too. In the end of the day, you just can’t enforce much and patterns like setter getter just gets in your way. Inherited thing can have altered behavior (even harder to catch when debug), as long as it’s not “final”.

btw sounds like you could use [GitHub - rafaqz/Mixers.jl: Julia mixin macros. Mixed, not stirred](https://github.com/rafaqz/Mixers.jl)

---

<div class="post-metadata">

### Author: ![lungben](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lungben/32/12314_2.png) [@lungben](https://discourse.julialang.org/u/lungben)
#### Post date: [August 28, 2021, 7:51am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/9 "2021-08-28T07:51:22Z")

</div>

This is the standard way to do it.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [August 28, 2021, 9:25am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/10 "2021-08-28T09:25:06Z")

</div>

This sounds like a toy problem (a classic one at that, looking at `Pet`. Almost sounds like the classic “suppose I have a type `Car` which has subtypes `Tesla`, `Audi`…”), do you have a more concrete example instead of only hypotheticals? Trying to model real life structure with subtyping relations is almost always a bad idea. There have been [a lot](https://discourse.julialang.org/search?q=inheritance) of threads with a similar theme though.

In any case, julia favors composition over inheritance, combined with a shallow type hierarchy. Defining an interface for `Pet` that all subtypes would have to adhere to is the way to go - if you find that you need _a lot_ of methods, it’s usually a good idea to think about a refactor away from one big “god” object and towards composition of smaller, more self contained objects.

---

<div class="post-metadata">

### Author: ![elenev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elenev/32/18440_2.png) [@elenev](https://discourse.julialang.org/u/elenev)
#### Post date: [August 28, 2021, 5:42pm UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/11 "2021-08-28T17:42:48Z")

</div>

@Sukera , you’re right. I tried to simplify things but probably simplified it too much.

Here’s the overall challenge. I have a method for solving a class of models. The specific models vary not just in terms of their parameter values but in terms of the list of parameters itself as well as in the equations, dimensions, etc. The method is general enough that it can handle all of these types.

To keep things simple, let’s suppose that the solution to a model is a vector x. Given a vector of parameters p, each model is a system of equations f(g(x,a),h(p,b)) = 0, where the system f, solution x, and parameters p are specific to each model, but where functions g and h and additional parameters a and b are common to all models of this class.

I wrote something like this:

```julia
struct Params
p1::Float64
end

struct GParams
a1::Float64
end

struct HParams
b1::Float64
end

struct Model
p::Params
a::GParams
b::HParams
end

# Abstracting away from how these functions are actually implemented
f(y,z)
g(x,a::GParams)
h(p,b::HParams)
initial_guess(p::Params)
update(x,err,p::Params)

function solve_model(mdl::Model, tol)
z = h(mdl.p, mdl.b)
x = initial_guess(p)
while true
  err = f(g(x,mdl.a), z)
  if maximum(abs.(err))<tol
    break
  else
    x = update(x,err,p)
  end
end
end

```

(Yes, I realize this looks like a generic nonlinear solver, and yes, I’m aware of NLsolve. The actual method is more complicated.)

What I would like to do is to break out `Gparams`, `HParams`, `g`, `h`, `update`, `solve_model` into their own module with an additional type e.g. `ModelClass`, on which `solve_model` will dispatch. Then the user can define their own `SpecificModel{P<:AbstractParams}` with its own `SpecificParams<:AbstractParams` and their own `f` and `initial_guess`.

But `solve_model` then needs access to the info in `a` and `b` and it needs to be able to call `initial_guess` and `f` that the user defined.

[Here](https://github.com/matthieugomez/EconPDEs.jl) is an example of a package that does something similar. But there the specific model (there are a few in `examples`) is entirely contained in one function (analogous to my `f`), so you can just pass the function to its equivalent of `solve_model`. In my example, there is one more (`initial_guess`) and in my actual application several more, so I can’t quite figure out how to adapt that design pattern to my case.

BTW, that package uses some strange syntax that I couldn’t find documented anywhere:

```julia
function (mdl::Model)(x)
return "$(mdl.onlyfield) $x"
end

```

which I think can be called by `a = Model(1); a(3)` which returns `1 3`. Can I read more about this somewhere?

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [August 28, 2021, 5:59pm UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/12 "2021-08-28T17:59:31Z")

</div>

> [@elenev](#):
>
> `function (mdl::Model)(x)`

this is simply saying `mdl::Model` is callable, and you can call it.

```julia
julia> struct A
           x
       end

julia> a = A(2)
A(2)

julia> a(3)
ERROR: MethodError: objects of type A are not callable
Stacktrace:
 [1] top-level scope
   @ REPL[3]:1

julia> (obj::A)(y) = obj.x + y

julia> a(3)
5

```

This pattern is [used a lot](https://github.com/FluxML/Flux.jl/blob/48f6ae90ea4d0b1b4d2c58a9e6d4d7cdceba71a4/src/layers/basic.jl#L156) in Flux.jl, where you can construct layers by passing shapes and activation function and the calling the layer will evaluate it.

---

<div class="post-metadata">

### Author: ![tsela](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tsela/32/52174_2.png) [@tsela](https://discourse.julialang.org/u/tsela)
#### Post date: [August 28, 2021, 6:02pm UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/13 "2021-08-28T18:02:02Z")

</div>

The syntax you’re referring to is simply described in the Julia documentation. See: [Methods · The Julia Language](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects)

---

<div class="post-metadata">

### Author: ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)
#### Post date: [August 28, 2021, 7:07pm UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/14 "2021-08-28T19:07:04Z")

</div>

Mixers.jl was my first julia package, feeling similar frustration to @elenev. But I literally never use it any more, it leads to bad designs. Use composition as @lmiq suggested in his example.

---

<div class="post-metadata">

### Author: ![elenev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elenev/32/18440_2.png) [@elenev](https://discourse.julialang.org/u/elenev)
#### Post date: [August 28, 2021, 9:05pm UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/15 "2021-08-28T21:05:40Z")

</div>

Thanks, all. BTW, I realize the topic has been discussed often but I was missing the right keywords to search for. Now that I know what to look for, these old threads were very relevant and interesting.

[Workaround for traditional inheritance features in object-oriented languages - General Usage - JuliaLang](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195)

The solutions are the same – either stick to OOP way of thinking about inheritance and use macros to work around Julia’s “limitations”, or adopt the composition approach suggested by @lmiq and @Sukera with the `Common` struct (perhaps renamed `PetState` or `PetData`) containing all the info that functions dispatching on abstract `Pet` need to be aware of.

There is still the slightly annoying book-keeping issue of accessing fields through nested `getproperty()` calls e.g.

```julia
struct Dog <: Pet
data::PetData
end

d = Dog(PetData("Fido"))
d.name # Error
d.data.name # returns "Fido"

```

But looks like Lazy.@forward can help save time implementing a bunch of pass-through methods like `get_name(pet::Pet) = pet.data.name`. Can probably even overload `getproperty()` but that could come with some performance issues.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [August 29, 2021, 5:45am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/16 "2021-08-29T05:45:05Z")

</div>

> [@elenev](#):
>
> But looks like Lazy.@forward can help save time implementing a bunch of pass-through methods like `get_name(pet::Pet) = pet.data.name` .

You don’t need that forward macro though, if your API for PetData is fixed. Since you presumably want to define and document the API in code anyway, why not define methods like these:

```julia
"""
    name(p::Pet)

Returns the name of the pet. The default implementation expects `p` to have a field `data`. 
"""
function name(p::Pet) 
   name(p.data)
end

```

where `Pet` is an abstract type.  
By virtue of dispatch and method specialization, if there’s no more specific method for a `p` of e.g. type `Dog <: Pet`, this will justWork™️ for subtypes of `Pet`. If people want to implement a more specific `name` method for their subtype, they’re free to do so and dispatch will select the correct one based on the type of `p`.

The forward macro is really only useful for wrapper types, where you want to encapsulate some other concrete type and you can’t change the fact that you’re wrapping a concrete type, where you also want to behave like that wrapped type. As I understand it, your usecase here doesn’t necessarily need a wrapped concrete type that you want to behave as, because you can seperate the data hierarchy (which is no hierarchy at all) from the type hierarchy by using an abstract super type.

---

<div class="post-metadata">

### Author: ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)
#### Post date: [August 29, 2021, 8:35am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/17 "2021-08-29T08:35:09Z")

</div>

> [@Raf](#):
>
> Mixers.jl was my first julia package, feeling similar frustration to @elenev. But I literally never use it any more, it leads to bad designs.

Can you recall a 'pattern" of those bad designs? (e.g. is it related to the use of helper macros in general, or comes from mixing in multiple fields for a single supertype instead of the “Common” stuct)

---

<div class="post-metadata">

### Author: ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)
#### Post date: [August 29, 2021, 9:03am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/18 "2021-08-29T09:03:16Z")

</div>

Mostly that you dont have the shared fields as an object you can dispatch on or use on its own, or swap out for a variant. That nearly always turns out to be useful.

Macros are also confusing and opaque to newcomers.

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [August 29, 2021, 11:18am UTC](https://discourse.julialang.org/t/method-inheritance-the-julian-way/67198/19 "2021-08-29T11:18:09Z")

</div>

we’re still trying to solve [https://github.com/tamasgal/UnROOT.jl/blob/master/src/bootstrap.jl](https://github.com/tamasgal/UnROOT.jl/blob/master/src/bootstrap.jl) with Mixers.jl haha, maybe oneday
