# Composition and inheritance: the Julian way

**URL:** <https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231>\
**Category:** General Usage\
**Tags:** inheritance, structtypes\
**Created:** [May 29, 2018, 1:06pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231 "2018-05-29T13:06:00Z")\
**Posts on this page:** 14\
**Page:** 7

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [October 25, 2021, 8:33pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/123 "2021-10-25T20:33:36Z")

</div>

> [@NightMachinary](#):
>
> re-defining **ONLY** those methods for which the `Foo` behaviour differs from the `X` one, which in the actual case are 3 or 4 (while the `X` object is accepted by hundred of method);

That’s the trickiest thing; actually I’d say that it’s generally _impossible_, but not for lack of tools, but because by definition there is no closed list of “methods for `X`” or “methods for `Foo`”.

`methodswith(X)` may help you get a list of methods that you would like to extend at some point, and with a bit of metaprogramming you might extend all of them at once so that they work for `Foo` instead of `X`.(\*) But then, maybe you do `using Bar`, which defines new methods for `X`, and your “extension” becomes incomplete.

And the “bad news” is that there is no way at all to anticipate what new methods may come from other packages. (Of course “bad news” only for the purpose of what we are discussing; in general that’s what makes composability easier.)

(\*) Even for a limited list of “methods for `X`”, extending them so that they take `Foo` instead of `X` is not always straightforward. For instance, how would you extend `*(::X, ::X)`? Shall it be `*(::Foo, ::Foo)`, or also other combinations with `X` and `Foo`?

---

<div class="post-metadata">

**Author:** ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)\
**Post date:** [October 25, 2021, 8:51pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/124 "2021-10-25T20:51:44Z")

</div>

Exactly. So Julia itself must have some rudimentary support of concrete single inheritance. Is there any technical difficulty in adding this?

---

<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:** [October 25, 2021, 9:00pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/125 "2021-10-25T21:00:14Z")

</div>

No, there is no structural inheritance. That’s what this whole thread is about. Having structural inheritance makes inlining much harder, forces the compiler to chase endless pointer chains by default and makes the size of an given struct possibly indeterminate (possibly preventing SIMD).

The point is that choosing composition over structural inheritance makes that choice _explicit_ and makes the job of the compiler easier. You can’t subtype concrete types in julia and abstract types don’t have fields. Together with functions and their arguments _not being coupled_ to any particular struct definition, you’re free to define methods extending a given implementation with your type _without having to touch the existing code at all_.

The functions (i.e. operations) define your API - not necessarily your struct layout, i.e. how you store what you need.

---

<div class="post-metadata">

**Author:** ![croberts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/croberts/32/9465_2.png) [@croberts](https://discourse.julialang.org/u/croberts)\
**Post date:** [October 27, 2021, 6:59pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/126 "2021-10-27T18:59:28Z")

</div>

Couldn’t you use a macro to do something like

```julia

@heritable struct MyParentType 
    my_field::SomeOtherType 
end

```

Which writes the code:

```julia
abstract type MyParentType end 
struct ConcreteMyParentType
   my_field::SomeOtherType 
end

```

and then write

```julia
@inherit struct MyChildType <: MyParentType 
    extra_field::SomeType
end

```

which writes the code:

```julia
struct MyChildType <: MyParentType
   parent_type::MyParentType 
   extra_field::SomeType
end 
MyChildType(x1::SomeOtherType, x2::SomeType) = new(MyParentType(x1), x2)
function getproperty(m::MyChildType, s::Symbol) 
    if s .∈ fieldnames(m)
        return getfield(m,s)
    else 
        return getfield(m.parent_type,s)
end

```

All methods defined on MyParentType are actually defined on an abstract type because the the macro defines the struct with the “concrete” prefix. Methods defined on MyParentType will correctly work on a subtype of MyParentType because the getfield function also looks for the fields in the parent type – unless the child type is given a field with the same name as a parent field.

I’m not sure if it would be possible to conveniently extend this approach to multiple inheritance, because you would have to write a macro extending methods defined on the second parent type to MyChildType, which is not a proper subtype of the other parent.

---

<div class="post-metadata">

**Author:** ![jlapeyre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlapeyre/32/4514_2.png) [@jlapeyre](https://discourse.julialang.org/u/jlapeyre)\
**Post date:** [October 27, 2021, 7:48pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/127 "2021-10-27T19:48:11Z")

</div>

People have written things like that. But, no one uses them. (and the author of the package below never intended for it to be used.)

[https://github.com/tbreloff/ConcreteAbstractions.jl](https://github.com/tbreloff/ConcreteAbstractions.jl)

---

<div class="post-metadata">

**Author:** ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)\
**Post date:** [October 28, 2021, 5:35pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/128 "2021-10-28T17:35:09Z")

</div>

The problem with these approaches is that they necessitate changes upstream.

---

<div class="post-metadata">

**Author:** ![wsshin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsshin/32/360_2.png) [@wsshin](https://discourse.julialang.org/u/wsshin)\
**Post date:** [January 23, 2022, 4:17pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/129 "2022-01-23T16:17:47Z")

</div>

Surprised that the following JuliaLang/julia Issue hasn’t been discussed here yet: [https://github.com/JuliaLang/julia/issues/4935](https://github.com/JuliaLang/julia/issues/4935). The proposed feature exactly addresses the problem debated here.

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [January 23, 2022, 8:10pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/130 "2022-01-23T20:10:33Z")

</div>

Just for reference for people reading this thread I figure I’d highlight [[ANN] CompositeStructs.jl](https://discourse.julialang.org/t/ann-compositestructs-jl/58902) which is maybe the least restrictive of these packages (ConcreteAbstractions.jl, Mixers.jl, Classes.jl, …) that try to mimick inheritance. Anyway, like the author of ConcreteAbstractions, I don’t feel strongly that this is a “great” solution that should be used alot, but maybe useful in certain situations.

---

<div class="post-metadata">

**Author:** ![merlin](https://avatars.discourse-cdn.com/v4/letter/m/8baadc/32.png) [@merlin](https://discourse.julialang.org/u/merlin)\
**Post date:** [June 29, 2022, 4:14pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/131 "2022-06-29T16:14:03Z")

</div>

This thread is gold. Got to this point and now I understand a lot more about OOP and Julia type dispatch style paradigms (which I like better, now I know why). FWIW I’m not a CS person.

---

<div class="post-metadata">

**Author:** ![tfinke](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tfinke/32/38995_2.png) [@tfinke](https://discourse.julialang.org/u/tfinke)\
**Post date:** [August 22, 2022, 10:26am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/132 "2022-08-22T10:26:37Z")

</div>

Hi dfdx,

your idea seems to solve my requirements exactly. I have to define a complex state that sometimes contains substates of partially the same entry types as the main state itself.

I wonder how to do this inheritance using Base.@kwdef. If I modify

```julia
res = :(mutable struct $name end)

```

into

```julia
res = :(Base.@kwdef mutable struct $name end)

```

I get the error: `syntax: invalid type signature`  
Seems it’s a matter of macro evaluation…

Thanks

Torsten

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [August 22, 2022, 10:43am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/133 "2022-08-22T10:43:00Z")

</div>

I didn’t really read this thread or the first post, just thought this new package might be of interest:

> [@\[ANN\] ObjectOriented.jl (renamed from TyOOP.jl), complete OOP support](https://discourse.julialang.org/t/ann-objectoriented-jl-renamed-from-tyoop-jl-complete-oop-support/83911):
>
> Hi community! It has been quite a long time since my last post, and now I’m glad to say that I have completed my postgraduate career and started working with Julia! sunglasses I made [this package (EDIT)](https://github.com/Suzhou-Tongyuan/ObjectOriented.jl) initially for the internal use in the company. It becomes open-source but I do get paid for this, which is pretty nice partying_face Anyway, this package provides relatively complete object-oriented programming support for Julia. The design is mainly based on Python’s object-oriented progr…

---

<div class="post-metadata">

**Author:** ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)\
**Post date:** [August 22, 2022, 1:07pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/134 "2022-08-22T13:07:45Z")

</div>

> [@tfinke](#):
>
> I get the error: `syntax: invalid type signature`  
> Seems it’s a matter of macro evaluation…

If ObjectOriented.jl doesn’t solve you problem, you can check what exactly is generated by the macro using `@macroexpand <expr>`.

---

<div class="post-metadata">

**Author:** ![Ken\_Williams](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ken_williams/32/5289_2.png) [@Ken\_Williams](https://discourse.julialang.org/u/Ken_Williams)\
**Post date:** [May 14, 2024, 5:12pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/135 "2024-05-14T17:12:31Z")

</div>

> [@Raf](#):
>
> Just learn multiple dispatch.

Wait a sec - I don’t see how multiple dispatch has much of anything to do with the composition/inheritance/reuse discussion happening in this discussion.

I’m totally on board with multiple dispatch and I don’t think it’s very hard to understand. But I’m desperately missing some kind of inheritance, by that name or any other.

I’m going to go read [Type-Dispatch Design: Post Object-Oriented Programming for Julia - Stochastic Lifestyle](https://www.stochasticlifestyle.com/type-dispatch-design-post-object-oriented-programming-julia/) and see if that helps me.

---

<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:** [May 14, 2024, 5:41pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/136 "2024-05-14T17:41:01Z")

</div>

I was being a bit blunt, but multiple dispatch really has a _lot_ to do with inheritance, because its the mechanism for defining traits.

I guess its not really clear what you mean by inheritance - fields or behaviors? But once you get used to it you wont miss anything, you are on a familiar arc.

> I’m totally on board with multiple dispatch and I don’t think it’s very hard to understand.

I guess there is more to it than a basic understanding. Have you written your own “holy traits”?

But heres an example of how multiple dispatch interacts with inheritance of fields and behaviors using composition. `Object` has some fields and behaviours of its own, and behaviors and even fields from `Style` objects. These influence the results of `some_function` using multiple dispatch.

```julia
abstract type Style end
struct StyleA <: Style end
struct StyleB <: Style
    val::Int
end

struct Object{S}
    style::S
    val::Bool
end

some_function(o::Object) = some_function(o.style, o)
some_function(::StyleA, o::Object) = o.val
some_function(t::StyleB, o) = t.val > 0

```

This function could be defined as a fallback for a new `StyleC` without any changes to `Object`

```julia
some_function(c::StyleC, o) = c.val^2 > 10

```

And by using `StyleC()` as your `style` in `Object` will give you `StyleC` behaviours. But you could additionally write a method to dispatch on both and handle the interaction.

(if youre still wondering why, now think about adding another composed object and dispatch for combinations of it and `Style`, and how you would just add another argument to `some_function` and define a few methods, and it will work and extend to whatever complexity of inheritance you need…)

[Previous page](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231.md?page=6)
