# Workaround for traditional inheritance features in object-oriented languages

**URL:** <https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195>\
**Category:** General Usage\
**Tags:** inheritance, structtypes\
**Created:** [December 29, 2016, 2:25am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195 "2016-12-29T02:25:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [December 29, 2016, 2:25am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/1 "2016-12-29T02:25:45Z")

</div>

I am using the Julia type system seriously for the first time and have just learned that it doesn’t support inheritance from non-abstract types nor multiple inheritance. This statement applies to Julia v0.5.

Could you please explain how one can workaround these limitations, specifically:

1. How you develop code with inheritance from abstract types only? Does it cover all possible use cases?
2. Is there any workaround for the lack of multiple inheritance?

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [December 29, 2016, 5:17am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/2 "2016-12-29T05:17:16Z")

</div>

(1) Inheriting from concrete types is often considered to be a design mistake in the languages that support it. It’s not clear to me that there’s any use case in which it’s required. It’s hard for me to imagine a case where inheritance from concrete types allows one to express something that couldn’t be achieved using composition, although I can imagine that inheritance removes some tedious repetition in some kinds of code.

(2) I think most Julia developers feel that a traits system would be superior to multiple inheritance for Julia. See Rust’s traits for an example of how traits are used in a modern language; Haskell’s type classes and C++'s concepts are also good topics to investigate. There are already several libraries that provide macros that provide basic trait-like functionality for Julia: I believe both Mauro and Andy Ferris have libraries for this.

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [December 29, 2016, 5:18am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/3 "2016-12-29T05:18:03Z")

</div>

To “work around” the absence of multiple inheritance approaches misframing the need. Julia’s features and facilities are multi-capable by design; and with some familiarity you will learn they intra-strenghen in application . The language does not underpin a computer software designer;s toolbox; it is different from systems that are as tools to the tool-makers. Julia facilitates coding the expressively obvious because Julia eases expressing collegial communication (processes and ideas). This “working with Julia’s way of working” is a better approach than would be “working around” an omission of initial familiarity.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 29, 2016, 6:24am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/4 "2016-12-29T06:24:42Z")

</div>

When I first moved from Python/C++/Matlab to Julia, I did find myself missing concrete inheritance. But as I learned more about how good Julia code is structured, that feeling faded.

One concrete suggestion I can offer is to focus on composition instead of inheritance. Where in Python you might do:

```python
class A:
    foo
    bar

class B(A):
    b

class C(A):
    c

```

in Julia you might choose to do:

```julia
type A
    foo
    bar
end

type B
    a::A
    b
end

type C
    a::A
    c
end

```

which has the added benefit of cleanly encapsulating all of the `A`-like behavior inside a single type, rather than mixing it into the behavior of `B` and `C`.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [December 29, 2016, 9:54am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/5 "2016-12-29T09:54:17Z")

</div>

@johnmyleswhite thank you for your answer. The tedious repetition you mention in (1) is the need for redefining every single method with the composite type? This is a big one.

Can you give an example of how traits can replace multiple inheritance?

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [December 29, 2016, 10:11am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/6 "2016-12-29T10:11:23Z")

</div>

Can you please comment on how this approach scales? It doesn’t seem practical to me, consider this simple example:

```julia
type Person
  name::String
  age::Int
end
age(p::Person) = p.age

type Employee
  person::Person
  id::Int
end
age(emp::Employee) = age(emp.person)

emp = Employee(Person("John",30),1)
age(emp)

```

Every time I instantiate a composite type, I need to explicitly call the constructor of the base type. Of course we can add sugar constructors to avoid this typing, but it is definitely tedious. Most annoying is the fact that we need to redefine (or wrap) every single method that applies to the base type so that it works with the derived type (e.g. `age` method).

Can you please explain how this approach is better than just having traditional inheritance?

---

<div class="post-metadata">

**Author:** ![tknopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tknopp/32/3569_2.png) [@tknopp](https://discourse.julialang.org/u/tknopp)\
**Post date:** [December 29, 2016, 10:37am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/7 "2016-12-29T10:37:57Z")

</div>

In your example a `hasa` relation does not make to much sense from my point of view  
Here would be my proposal:

```julia
abstract AbstractPerson
age(p::AbstractPerson) = p.age
name(p::AbstractPerson) = p.name

type Person <: AbstractPerson
  name::String
  age::Int
end

type Employee <: AbstractPerson
  name::String
  age::Int
  id::Int
end
id(p::Employee) = p.id

emp = Employee("John",30,1)
age(emp)

```

The point is actually to think about the interface that you want for your types. The interface should be a set of functions that the type is going to implement. You see some repetition in the above code but in practice this is not a big issue if you prevent deep type hierarchies.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [December 29, 2016, 10:59am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/8 "2016-12-29T10:59:21Z")

</div>

@tknopp this is a very disconnected interface, the type system doesn’t know `Person` and `Employee` are related. Also, in this snippet of code you do not only provide the interface, you implement it in the base, which is not practical with slightly more complicated methods. The implementation may (and will likely) change depending on the type.

The fact that an `Employee` is also a `Person` is quite important to keep things organized in the system.

---

<div class="post-metadata">

**Author:** ![tknopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tknopp/32/3569_2.png) [@tknopp](https://discourse.julialang.org/u/tknopp)\
**Post date:** [December 29, 2016, 11:03am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/9 "2016-12-29T11:03:03Z")

</div>

Sorry I missed to inherit from the abstract type. Is corrected in the above example

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [December 29, 2016, 11:06am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/10 "2016-12-29T11:06:01Z")

</div>

Got it, thanks. We still have the issue of implementing the interface in the base with this approach.

---

<div class="post-metadata">

**Author:** ![tknopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tknopp/32/3569_2.png) [@tknopp](https://discourse.julialang.org/u/tknopp)\
**Post date:** [December 29, 2016, 11:11am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/11 "2016-12-29T11:11:25Z")

</div>

This is not really an issue depending how pure your thinking is. The methods

> [@tknopp](#):
>
> age(p::AbstractPerson) = p.age  
> name(p::AbstractPerson) = p.name

say that any subtype needs to implement these two and that `p.age` and `p.name` are the default fields that will be used. You are free to `override` this by a definition

```julia
name(p::Employee) = "Superman"

```

---

<div class="post-metadata">

**Author:** ![tknopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tknopp/32/3569_2.png) [@tknopp](https://discourse.julialang.org/u/tknopp)\
**Post date:** [December 29, 2016, 11:15am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/12 "2016-12-29T11:15:19Z")

</div>

Its also important to note that these are all just the low level methods. If you implement high level algorithms that involve the methods `age` and `name` you will always implement against the abstract interface and in turn only have to provide a single implementation. So with larger code the issue actually gets less relevant.

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [December 29, 2016, 11:22am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/13 "2016-12-29T11:22:41Z")

</div>

Regarding the concrete inheritance, this thread is very useful:  
[https://groups.google.com/d/topic/julia-users/qj-ivya6l8A/discussion](https://groups.google.com/d/topic/julia-users/qj-ivya6l8A/discussion)

The basic idea is that if your goal is code reuse, then use composition, not inheritance. Inheritance is for common behavior, and behavior is implemented in methods in Julia, and those can be defined on an abstract type and overridden for any other type in the hierarchy. The tradeoffs are discussed at length in the links @ChrisRackauckas posted in that thread.

---

<div class="post-metadata">

**Author:** ![danielc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielc/32/220_2.png) [@danielc](https://discourse.julialang.org/u/danielc)\
**Post date:** [December 29, 2016, 11:24am UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/14 "2016-12-29T11:24:01Z")

</div>

I agree with @juliohm here. As much as I like Julia, it really doesn’t seem well-suited for class-based OOP. In the “employee vs person” example, the problem is very naturally stated in the language of concrete inheritance. Julia seems to be taking a simple problem and making it needlessly hard. I think we should just admit that Julia doesn’t do a good job here and maybe think about whether there is a reasonable way the language could be improved.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [December 29, 2016, 2:16pm UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/15 "2016-12-29T14:16:59Z")

</div>

Julia doesn’t have classes so it seems pretty self evident for me that it isn’t suited for “class-based OOP”… So yeah, trying to design your type hierarchies exactly as you would in OOP is likely not going to be optimal.

> [@danielc](#):
>
> Julia seems to be taking a simple problem and making it needlessly hard

Comments like that are just inflammatory. Please consider the case that you haven’t actually understood the problem and the implications of “fixing” it.

> [@danielc](#):
>
> I think we should just admit that Julia doesn’t do a good job here and maybe think about whether there is a reasonable way the language could be improved.

Same here. It is often better to take the position of a student than a teacher. Do you really feel your expertise is high enough that you can state what you are stating as confidently as you do.

---

<div class="post-metadata">

**Author:** ![pint](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pint/32/125_2.png) [@pint](https://discourse.julialang.org/u/pint)\
**Post date:** [December 29, 2016, 3:23pm UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/16 "2016-12-29T15:23:52Z")

</div>

as a general rule, the best practice is to work _with_ the platform, and not _against_ the platform. OOP thinking should be left at the door, because Julia is not an OOP language. you need to approach the problem with the tools you have at hand, not trying to reimplement the tools you used to have.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [December 29, 2016, 4:51pm UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/17 "2016-12-29T16:51:21Z")

</div>

> [@danielc](#):
>
> As much as I like Julia, it really doesn’t seem well-suited for class-based OOP. In the “employee vs person” example, the problem is very naturally stated in the language of concrete inheritance.

Real-world problems aren’t well-suited for inheritance-based OOP either, which is why you’re generally told/taught to not use inheritance in OOP, except in your first undergrad class where you learn about OOP and program design. Here’s three links discussing why considered using these features is considered bad practice (even in OOP languages).

> **[Composition over inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance)**
>
> Composition over inheritance (or composite reuse principle) in object-oriented programming (OOP) is the principle that classes should favor polymorphic behavior and code reuse by their composition (by containing instances of other classes that implement the desired functionality) over inheritance from a base or parent class. Ideally all reuse can be achieved by assembling existing components, but in practice inheritance is often needed to make new ones. Therefore inheritance and object composi An...

> <https://softwareengineering.stackexchange.com/questions/134097/why-should-i-prefer-composition-over-inheritance>

> **[Composition vs. Inheritance: How to Choose?](https://www.thoughtworks.com/insights/blog/composition-vs-inheritance-how-choose)**
>
> In the Beginning...
> ...there was no inheritance and no composition, only code.
> And the code was unwieldy, repetitive, blocky, unhappy, verbose, and tired.
> Copy and Paste were the primary mechanisms of code reuse. Procedures and functions were rare,...

So that begs the question, if every style guide is against inheritance and for composition, why do people push so hard to have inheritance implemented when composition comes very natural to Julia through multiple dispatch?

Let me elaborate on that last part a bit. Say you want

```julia
type B <: HoldsAnA
  a::A
end

```

to act like an `A` in many places. Then you can `f(b::B) = f(b.a)` and dispatch handles the rest (and implicit returns makes that function that easy). You can even make an entire “class” of types “inherit” this ability via `f(b::HoldsAnA) = f(b.a)`.

You can do multiple inheritance of behavior via traits. For more information on that, check out [SimpleTraits.jl](https://github.com/mauro3/SimpleTraits.jl). Essentially, you can make some type have a trait, and just dispatch functions on that trait. You can use that to make functions give a value:

```julia
@traitfn islinear(x::::IsLinear) = true
@traitfn islinear(x::::(!IsLinear)) = false

```

so instead of looking for “an inherited field” `x.islinear`, this is “an inherited function call” `islinear(x)`… but guess what? Unlike a field of a mutable object, this is known at compile time and thus results in faster code!

Now lets say you got to here and are like, well I still want inheritance. Well, you can take the 10 minutes to make it yourself. A poor man’s way is just via `@def`:

```julia
macro def(name, definition)
    return quote
        macro $(esc(name))()
            esc($(Expr(:quote, definition)))
        end
    end
end

```

You can use this macro to do compile-time copy/paste, which is essentially what inheritance of fields is. So you can do:

```julia
@def the_fields begin
  x::Float64
  y::Float64
end

type A
  @the_fields
   z::Float64
end

type B
  @the_fields
end

```

and there you go. What if you want to go all of the way? Here’s a good introduction to meta-programming project: implement this design:

```julia
@inheritable X{T} begin
  x::{T}
  y::Float64
end

@inherits type A
  X
  z::Float64
end

@inherits type B
  X
end

```

The tricky part is making it produce `A{T}` (but make it general enough so you can have `X{T}` with `z::T` and get `A{T,T2}`. Hint: use `gensym`), but all of the information is there. So if you still really Really REALLY need OOP-style inheritance, there you go: it’s a fun weekend project.

This question gets asked enough that this response might need to be a blog post so I can just paste it around.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [December 29, 2016, 8:19pm UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/18 "2016-12-29T20:19:09Z")

</div>

> This question gets asked enough that this response might need to be a blog post so I can just paste it around.

Please do, @ChrisRackauckas!

@juliohm Once you can get past the idea that current “OO” techniques are somehow better than the flexible type system (getting much better shortly, when #18457 is merged), combined with multiple dispatch and emerging things such as traits, I think you’ll find yourself amazed at the power available in Julia, and you’ll end up feeling greatly limited in most any other language out there.

---

<div class="post-metadata">

**Author:** ![danielc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielc/32/220_2.png) [@danielc](https://discourse.julialang.org/u/danielc)\
**Post date:** [December 29, 2016, 8:30pm UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/19 "2016-12-29T20:30:29Z")

</div>

> [@kristoffer.carlsson](#):
>
> Comments like that are just inflammatory.

Why? Look, I did not mean my comment to be inflamantory and I don’t understand why you feel that it is. I thought that I was objective and polite. Why is it wrong to say that X problem is needlessly hard in Y language? There isn’t a language in the world that is ideally suited for every problem. I could name any language in the world and you could easily list problems that it makes needlessly difficult.

> [@kristoffer.carlsson](#):
>
> Please consider the case that you haven’t actually understood the problem and the implications of “fixing” it.

What are you talking about? I did not suggest a fix. I said “_think about whether there is a reasonable way the language could be improved._” — There is an implicit recognition that maybe there **_isn’t_** any reasonable way to improve the language. I don’t claim to know whether there is a reasonable solution or not.

> [@kristoffer.carlsson](#):
>
> It is often better to take the position of a student than a teacher.

I agree. And I thought I did. At least, that was my intention.

> [@kristoffer.carlsson](#):
>
> Do you really feel your expertise is high enough that you can state what you are stating as confidently as you do.

What am I stating? That I think we should admit that Julia cannot do X and that people smarter than me might want to think about whether there is a reasonable way to improve the language? I don’t see how I could have made the statement milder unless I am not allowed to say that Julia isn’t suited for class-based OOP, but you yourself agreed that this is the case in the first sentence of your response. I don’t understand why my post is inflamatory and yours isn’t when you said the same thing that I said.

---

<div class="post-metadata">

**Author:** ![danielc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielc/32/220_2.png) [@danielc](https://discourse.julialang.org/u/danielc)\
**Post date:** [December 29, 2016, 8:34pm UTC](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195/20 "2016-12-29T20:34:50Z")

</div>

> [@ChrisRackauckas](#):
>
> Real-world problems aren’t well-suited for inheritance-based OOP either, which is why you’re generally told/taught to not use inheritance in OOP, except in your first undergrad class where you learn about OOP and program design.

Thanks. I’ll have a look when I get a chance. But to be clear, _I_ did not ask for OOP features. If I wanted to write inheritance-based OOP I’d just pick up Python or Ruby rather than fight with Julia. I use Julia for numerical stuff like data analysis. I use Julia for problems that Julia is meant to solve and solves well.

[Next page](https://discourse.julialang.org/t/workaround-for-traditional-inheritance-features-in-object-oriented-languages/1195.md?page=2)
