# 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:** 20\
**Page:** 5

<div class="post-metadata">

**Author:** ![gcalderone](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gcalderone/32/1539_2.png) [@gcalderone](https://discourse.julialang.org/u/gcalderone)\
**Post date:** [January 16, 2019, 3:12pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/82 "2019-01-16T15:12:35Z")

</div>

@WschW, thanks for pointing it out. I completely missed it…

The functionalities are very similar to `@quasiabstract`, with the following differences:

- `@protostruct` store the field names and types in a global register, while `@quasiabstract` uses Julia introspection facilities;
- in `StructuralInheritance` both the abstract and the concrete tape name are required in the code (respectively, to annotate function types and to call the constructor), while in `ReusePattern` I define constructors with the same name as the abstract type, hence the user may simply forget about the name of the concrete type.

I added the link to the list of package providing similar functionalities in the [README.md](https://github.com/gcalderone/ReusePatterns.jl/blob/master/README.md).

---

<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:** [January 16, 2019, 3:15pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/83 "2019-01-16T15:15:21Z")

</div>

> [@gcalderone](#):
>
> I agree: we need to formalize the way we approach the problem, and document it once and for all. As I said above, the most useful part of `ReusePatterns.jl` is probably its README.md file

> the most useful part of ReusePatterns.jl is probably its README.md

+a\_big\_number. I was going to say that, but you beat me to it. It’s the beginning of a review of approaches.

Even review and redesigning of simpler parts of the language; eg rationalizing sorting or searching was a large undertaking.

My impression is that it will take a lot of research (practical research) and experience to hit on design patterns. The tools will grow in solidity as effective patterns become clear.

I’m not the one to do it. I was trained as a physicist, not a software engineer. I’m struggling now to design good interfaces for random walk simulations. Thinking hard about interfaces is new to me. (I’ve written a ton of simulations over the years, but it’s never very resuable.) Doing it when the options are not clear is even harder. But, I appreciate you gathering resources.

---

<div class="post-metadata">

**Author:** ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)\
**Post date:** [January 17, 2019, 3:26am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/84 "2019-01-17T03:26:33Z")

</div>

Those are the major differences but there are two more minor differences which hopefully will change.

- `@quasiabstract` does not yet support the creation or inheritance of parametric types.

```julia
julia> using ReusePatterns

julia> @quasiabstract struct A{T}
          f1::T
       end
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] top-level scope at none:0

```

- `@protostruct` has a vulnerability that `@quasiabstract` does not have:

```julia
julia> using StructuralInheritance

julia> g(x) = Int
g (generic function with 1 method)

julia> @protostruct struct B
           f1::g(1)
       end
ProtoB

julia> g(x::Int) = Float64
g (generic function with 2 methods)

julia> @protostruct struct C <: B end
ProtoC

julia> @doc C
  No documentation found.

  Summary
  ≡≡≡≡≡≡≡≡≡

  struct C <: ProtoC

  Fields
  ≡≡≡≡≡≡≡≡

  f1 :: Float64

  Supertype Hierarchy
  ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡

  C <: ProtoC <: ProtoB <: Any

```

---

<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:** [January 17, 2019, 4:59am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/85 "2019-01-17T04:59:07Z")

</div>

It shouldn’t be too hard to allow macro and parametric type reuse, Mixers.jl does both fine even with multiple inheritance.

---

<div class="post-metadata">

**Author:** ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)\
**Post date:** [January 17, 2019, 6:22am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/86 "2019-01-17T06:22:36Z")

</div>

> [@Raf](#):
>
> It shouldn’t be too hard to allow macro and parametric type reuse, Mixers.jl does both fine even with multiple inheritance.

Approaching what `Mixers.jl` shouldn’t be too difficult for `ReusePatterns.jl` UnionAll types store type parameters in the var field, and getting the TypeVar of a field type is just a small change, though it does require utilizing an undocumented and non-exported function from base.

```julia
julia> fieldtype(Complex,1)
Real

julia> fieldtype(Base.unwrap_unionall(Complex),1)
T<:Real

```

However, way that parametrics work in Mixers does not allow for inheriting from a specialized parameter this is something you may want to do when inheriting structure in a non-mixin way for example:

```julia
julia> using StructuralInheritance

julia> @protostruct struct A{T}
           fieldFromA::T
       end
ProtoA

julia> @protostruct struct B{D} <: A{Complex{D}}
          fieldFromB::D
       end "SomeOtherPrefix"
SomeOtherPrefixB

julia> @protostruct struct C <: B{Int}
         fieldFromC
       end
ProtoC

julia> @doc C
  No documentation found.

  Summary
  ≡≡≡≡≡≡≡≡≡

  struct C <: ProtoC

  Fields
  ≡≡≡≡≡≡≡≡

  fieldFromA :: Complex{Int64}
  fieldFromB :: Int64
  fieldFromC :: Any

  Supertype Hierarchy
  ≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡

  C <: ProtoC <: SomeOtherPrefixB{Int64} <: ProtoA{Complex{Int64}} <: Any

```

This is more complex than what `Mixers.jl` does.

Another concern for inheritance is qualifying types, for example we can see that Mixers currently does not qualify types:

```julia
julia> using Mixers
[Info: Precompiling Mixers [2a8e4939-dab8-5edc-8f64-72a8776f13de]

julia> module M_1
           using ..Mixers
           struct A end
           @premix struct B; f1::A; end
       end
Main.M_1

julia> M_1.@B struct C end
ERROR: UndefVarError: A not defined
Stacktrace:
 [1] top-level scope at none:0

julia> 

```

This is not an issue for `ReusePatterns.jl` (it directly uses types from introspection), or for `StructuralInheritance.jl` (it qualifies function and type names).

---

<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:** [January 17, 2019, 6:26am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/87 "2019-01-17T06:26:56Z")

</div>

You have to put the empty brackets on C.

From the readme:

> “One gotcha is the need to put empty curly braces on a struct with no parametric fields, if it is going to have parametric fields after @mix or @premix. This keeps Mixers.jl code simple, and is a clear visual reminder that the struct is actually parametrically typed”

I thought about inserting the brackets in the macro, but actually I like that I can tell when there are parametric types. But I would accept a pull request if people really hated that behaviour.

---

<div class="post-metadata">

**Author:** ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)\
**Post date:** [January 17, 2019, 6:31am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/88 "2019-01-17T06:31:20Z")

</div>

that example does not use parametric fields, this is an issue of type qualification which shows which module a type was defined in, taking the same code and putting everything in one module works just fine:

```julia
julia> struct A end

julia> using Mixers

julia> struct A end

julia> @premix struct B; f1::A; end
@B (macro with 1 method)

julia> @B struct C end

julia> 

```

---

<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:** [January 17, 2019, 6:36am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/89 "2019-01-17T06:36:22Z")

</div>

Ah ok I misread that capital A as a parametric type.

That’s a bug then.

---

<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:** [January 17, 2019, 6:55am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/90 "2019-01-17T06:55:52Z")

</div>

As for the first example, if I understand what is happening. Inheriting from a specialised parameter is interesting, but Mixers can’t do inheritance like that because it’s made to allow multiple inheritance! I often have a couple of mixins chained and multiple trait dispatches on the same struct.

I was meaning to say this earlier, I think there are three fundamental approaches here - link field reuse to abstract types as both ReusePatterns and StructuralInheritance do, or link field reuse to traits, or do neither and leave connecting fields and behaviours up to the user.

Mixers does neither. Although I will probably add a `@traitmix` macro option to automate the trait generation, as that’s what I do most of the time.

---

<div class="post-metadata">

**Author:** ![gcalderone](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gcalderone/32/1539_2.png) [@gcalderone](https://discourse.julialang.org/u/gcalderone)\
**Post date:** [January 17, 2019, 7:29am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/91 "2019-01-17T07:29:20Z")

</div>

> [@WschW](#):
>
> `@quasiabstract` does not yet support the creation or inheritance of parametric types.

Fixed in the master branch. The creation of the structure was ok, there was a problem in the constructor. Thank you for finding it!!

---

<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:** [January 28, 2019, 10:31am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/92 "2019-01-28T10:31:15Z")

</div>

Turns out you can just qualify A in the mixin and your example works fine:

```julia
julia> using Mixers
module M_1

julia> module M_1
          using ..Mixers
          struct A end
          @premix struct B; f1::M_1.A; end
       end
Main.M_1

julia> M_1.@B struct C end

julia> 

```

---

<div class="post-metadata">

**Author:** ![atthom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/atthom/32/7173_2.png) [@atthom](https://discourse.julialang.org/u/atthom)\
**Post date:** [February 22, 2019, 3:09pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/93 "2019-02-22T15:09:39Z")

</div>

Hi everyone,  
I was looking for type inheritance in Julia and find out your discussion.

For me and for most relatively experienced developers, POO is the natural approach when creating what we call here “Composite Types”.  
I don’t really care if it’s a generated-by-macro composition behind the scenes, as long as I have a simple way to do it.

What I think is a problem is you have _too many_ solutions for this simple problem.  
So far I’ve found these packages that could potentially solve my problem:

- [GitHub - tbreloff/ConcreteAbstractions.jl: Concrete type inheritance for Julia](https://github.com/tbreloff/ConcreteAbstractions.jl)
- [GitHub - WschW/StructuralInheritance.jl: pseudo structural inheritance for the Julia language](https://github.com/WschW/StructuralInheritance.jl)
- [GitHub - gcalderone/ReusePatterns.jl: Implement composition and concrete subtyping in Julia.](https://github.com/gcalderone/ReusePatterns.jl)

- Writing the macro myself which is definitely the worst idea because I’m not an experienced Julia developer.

If everyone picks a different way of doing pseudo-inheritance this is going to be a problem in terms of readability.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 22, 2019, 3:33pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/94 "2019-02-22T15:33:58Z")

</div>

> [@atthom](#):
>
> for most relatively experienced developers, POO is the natural approach

What is POO?

> [@atthom](#):
>
> What I think is a problem is you have _too many_ solutions for this simple problem.  
> So far I’ve found these packages that could potentially solve my problem:

For composition, you don’t really need a package. Some packages have a `@forward` macro to make method dispatch easier, but it’s not that big of a deal to just write it out. And as a bonus, it is very readable.

---

<div class="post-metadata">

**Author:** ![ianfiske](https://avatars.discourse-cdn.com/v4/letter/i/58f4c7/32.png) [@ianfiske](https://discourse.julialang.org/u/ianfiske)\
**Post date:** [February 22, 2019, 4:03pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/95 "2019-02-22T16:03:17Z")

</div>

And for completeness, here’s an even-longer list of packages aiming to help with this: [https://github.com/gcalderone/ReusePatterns.jl#pacakges-providing-similar-functionalities](https://github.com/gcalderone/ReusePatterns.jl#pacakges-providing-similar-functionalities).

---

<div class="post-metadata">

**Author:** ![atthom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/atthom/32/7173_2.png) [@atthom](https://discourse.julialang.org/u/atthom)\
**Post date:** [February 22, 2019, 6:49pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/96 "2019-02-22T18:49:55Z")

</div>

It’s OOP, sorry. Oriented Object Programming.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 22, 2019, 7:03pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/97 "2019-02-22T19:03:14Z")

</div>

Thanks for clarifying. In that case, it is not obvious to me that

> [@atthom](#):
>
> for most relatively experienced developers, [it] is the natural approach

Incidentally, I found [Your Code: OOP or POO?](https://blog.codinghorror.com/your-code-oop-or-poo/)  
which may explain why — most of what is used in more traditional OOP may not translate well into Julia.

---

<div class="post-metadata">

**Author:** ![atthom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/atthom/32/7173_2.png) [@atthom](https://discourse.julialang.org/u/atthom)\
**Post date:** [February 22, 2019, 8:26pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/98 "2019-02-22T20:26:53Z")

</div>

I said “most” because the current popular languages are indeed OOP language such as Java, Python or C++.

And developers that comes into Julia have a high probability to be already fluent theses languages, much more than any FP language.

I’m not judging if OOP is good or bad. It’s just a paradigm that developers are more familiar with.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 22, 2019, 9:39pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/99 "2019-02-22T21:39:32Z")

</div>

Pardon my question, here, but, aren’t there plenty of OOP languages already? If you prefer that to multiple dispatch, what draws you to Julia? Ditching old fashioned OOP for something more powerful is sort of the point.

---

<div class="post-metadata">

**Author:** ![atthom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/atthom/32/7173_2.png) [@atthom](https://discourse.julialang.org/u/atthom)\
**Post date:** [February 22, 2019, 10:28pm UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/100 "2019-02-22T22:28:21Z")

</div>

I came to Julia for efficiency and ease of use, not for multiple dispatch.  
I take all the functionalities that Julia has to offer and if OOP is not that efficient I’m okay with that.

I said that what happened behind the scenes is not really important for me.

Actually, with the number of packages designed especially for rewriting OOP code into Julia’s efficient type system, this is clearly something that developers want.

---

<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:** [February 23, 2019, 12:46am UTC](https://discourse.julialang.org/t/composition-and-inheritance-the-julian-way/11231/101 "2019-02-23T00:46:18Z")

</div>

Don’t count me in your list I just want slightly more code reuse. I’m sure most of the competing solutions you mention will die in the next few years anyway (except mine of course 😉 , which has nothing to do with OOP)

Just learn multiple dispatch.

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

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