# Inserting new abstract type into existing hierarchy?

**URL:** <https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365>\
**Category:** General Usage\
**Tags:** question, design-pattern\
**Created:** [June 3, 2021, 11:19pm UTC](https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365 "2021-06-03T23:19:34Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![lamorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lamorton/32/21115_2.png) [@lamorton](https://discourse.julialang.org/u/lamorton)\
**Post date:** [June 3, 2021, 11:19pm UTC](https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365/1 "2021-06-03T23:19:34Z")

</div>

Suppose an existing package `Barnyard` defines

```julia
abstract type Animal end
abstract type Dog <: Animal end

```

Let’s say that in my package `Zoo` I define two new types:

```julia
using Barnyard
abstract type Zebra <: Animal end
abstract type Lizard <: Animal end

```

But, now I want certain method to apply to `Zebra` and `Dog` while a different one should apply to types such as `Lizard`. I want an intervening type `Mammal` that sits above both `Zebra` and `Dog` and below `Animal`. (Also maybe a `Reptile` type for `Lizard` to go under, but that’s easy.)

Let’s suppose the maintainers of `Barnyard` reject my PR for some reason, and I don’t want to maintain a hard fork. Is there a way to `inject` an intermediate level into the type hierarchy from outside the package? It seems like it is not possible:

```julia
using Barnyard
abstract type Mammal <: Animal end
abstract type Zebra <: Mammal end
abstract type Dog <: Mammal end

```

The last line here fails with:

```julia
ERROR: invalid redefinition of constant Dog

```

I suppose I could use `Mammal = Union(Dog,Zebra)` but this seems not very sustainable.

---

<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:** [June 3, 2021, 11:46pm UTC](https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365/2 "2021-06-03T23:46:27Z")

</div>

You have to restart julia to redefine type 🙂

---

<div class="post-metadata">

**Author:** ![lamorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lamorton/32/21115_2.png) [@lamorton](https://discourse.julialang.org/u/lamorton)\
**Post date:** [June 4, 2021, 12:25am UTC](https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365/3 "2021-06-04T00:25:22Z")

</div>

Thanks, I’m already doing that though. The issue is rather that I’m not able to declare that `Dog` is a subtype of `Mammal`.

---

<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:** [June 4, 2021, 12:32am UTC](https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365/4 "2021-06-04T00:32:54Z")

</div>

Ahh I skim read the “existing package” part

You can’t redefine an existing type in another package, it’s not a thing. You need to use holy traits instead. You can even do that with existing abstract types, which could be something like:

```julia
category(::Animal) = Animal
category(::Dog) = Mammal

somemethod(animal::Animal) = somemethod(category(animal), animal)
somemethod(::Type{<:Mammal}, animal) = ...
somemethod(::Type{<:Animal}, animal) = ... # fallback

```

---

<div class="post-metadata">

**Author:** ![lamorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lamorton/32/21115_2.png) [@lamorton](https://discourse.julialang.org/u/lamorton)\
**Post date:** [June 4, 2021, 1:29am UTC](https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365/5 "2021-06-04T01:29:08Z")

</div>

I see. I didn’t intend to redefine the type, only to add new information about how the types relate. But, it looks like this is related to [the discussion about multiple inheritance](https://discourse.julialang.org/t/why-does-julia-not-support-multiple-traits/5278/44). I’m not actually interested in multiple inheritance in this case (turning the type tree into a type lattice), just in ‘stretching’ the existing type tree by interposing a new node that I can stick new branches onto. But, if one _were_ able to declare new supertypes after the fact, it would (in general) allow to create multiple inheritance, which is apparently a difficult feature to implement with multiple dispatch & hasn’t been done yet (might never be done). I’m curious if this simpler case would be easier to implement than the general case, but it’s probably not trivial either.

Thanks for the info about Holy traits. I think this probably good enough for what I am doing.

---

<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:** [June 4, 2021, 1:37am UTC](https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365/6 "2021-06-04T01:37:47Z")

</div>

I imagine it would cause hell for method dispatch and code caching if you could insert types into the hierarchy at will, anywhere in the ecosystem. But that’s a guess.

---

<div class="post-metadata">

**Author:** ![lamorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lamorton/32/21115_2.png) [@lamorton](https://discourse.julialang.org/u/lamorton)\
**Post date:** [June 4, 2021, 1:53am UTC](https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365/7 "2021-06-04T01:53:45Z")

</div>

I’m leaning toward “not causing hell”: any methods that are not aware of the insertion of `Mammal` would continue to work just fine, since the original supertype (`Animal` here) would still be a supertype of `Dog`, so the dispatch should work its way up to the original supertype and then get the original method appropriate for that. However, if I were to specialize an existing function for `Animal` with a method for `Mammal`, that would constitute type piracy I think, and could cause real problems.

---

<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:** [June 4, 2021, 2:05am UTC](https://discourse.julialang.org/t/inserting-new-abstract-type-into-existing-hierarchy/62365/8 "2021-06-04T02:05:24Z")

</div>

Ok… but as a random example in practice the code for supertype is:

```julia
function supertype(T::DataType)
    @_pure_meta
    T.super
end

```

So allowing this to change at will will break method purity, and that will have performance consequences.
