# Inherit.jl

**URL:** https://discourse.julialang.org/t/inherit-jl/99102
**Category:** Package Announcements
**Tags:** package, announcement
**Created:** [May 19, 2023, 9:47am UTC](https://discourse.julialang.org/t/inherit-jl/99102 "2023-05-19T09:47:01Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![Kirby\_Zhang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kirby_zhang/32/36204_2.png) [@Kirby\_Zhang](https://discourse.julialang.org/u/Kirby_Zhang)
#### Post date: [May 19, 2023, 9:47am UTC](https://discourse.julialang.org/t/inherit-jl/99102/1 "2023-05-19T09:47:01Z")

</div>

I’m happy to announce the first release of [Inherit.jl](https://github.com/mind6/Inherit.jl). The package provides a simple way to inherit fields and interface definitions in Julia. it is currently available in the general registry (`] add Inherit`).

Example:

```julia
using Inherit

"
Base type of Fruity objects. 
Creates a julia native type with 
	`abstract type Fruit end`
"
@abstractbase struct Fruit
	weight::Float64
	"declares an interface which must be implemented"
	function cost(fruit::Fruit, unitprice::Float64) end
end

"
Concrete type which represents an apple, inheriting from Fruit.
Creates a julia native type with 
	`struct Apple <: Fruit weight::Float64; coresize::Int end`
"
@implement struct Apple <: Fruit 
	coresize::Int
end

"
Implements supertype's interface declaration `cost` for the type `Apple`
"
function cost(apple::Apple, unitprice::Float64)
	apple.weight * unitprice * (apple.coresize < 5 ? 2.0 : 1.0)
end

println(cost(Apple(3.0, 4), 1.0))

```

```julia
6.0

```

It works with multiple levels of inheritance and across different modules. The package grew out of a simple idea but implementing was quite tricky and was not really mature for several months. This version I believe is finally usable for most people. Feedback and contributions are welcome!

Kirby

---

<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: [May 19, 2023, 11:27am UTC](https://discourse.julialang.org/t/inherit-jl/99102/2 "2023-05-19T11:27:22Z")

</div>

Is this (partially) redundant with many other OOP packages (there’s also OOPMacro.jl and CBOO something):

> [@\[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: ![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 19, 2023, 1:47pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/3 "2023-05-19T13:47:09Z")

</div>

I’m not sure what you’re getting here that you don’t get from Mixers.jl, which is only 100 lines, and is independent from the inheritance mechanism.

---

<div class="post-metadata">

### Author: ![nandoconde](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nandoconde/32/19497_2.png) [@nandoconde](https://discourse.julialang.org/u/nandoconde)
#### Post date: [May 19, 2023, 2:14pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/4 "2023-05-19T14:14:03Z")

</div>

Hey, guys, let’s keep it positive.

First of all, congratulations on your package!

Maybe, could you elaborate a bit more on the differences between your package and those mentioned?

Thanks, and congrats again!

---

<div class="post-metadata">

### Author: ![Kirby\_Zhang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kirby_zhang/32/36204_2.png) [@Kirby\_Zhang](https://discourse.julialang.org/u/Kirby_Zhang)
#### Post date: [May 19, 2023, 2:15pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/5 "2023-05-19T14:15:37Z")

</div>

The main difference I can see is they don’t seem to verify method signatures. Their interface seems to be only checking for a function name?

Found this post about ObjectOriented.jl

> [@\[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/18):
>
> This is a really cool package, thank you for sharing it. While I’m really not so keen on the whole OOP stuff, I do indeed think that type/field inheritance (like the example in this post) might be really nice for ABMs (my main field of research). So maybe this is something to try out in the future to see how well it works for my use case. slight_smile While reading through the docs, I’ve stumbled upon something that frankly bugs me a bit though. As outlined [here](https://suzhou-tongyuan.github.io/TyOOP.jl/dev/cheat-sheet-en/#.-Inheritance), regular type checks in Julia …

This problem is avoided in Inherit.jl,

```julia
a = Apple(1,2)
a isa Apple && a isa Fruit

```

```julia
true

```

Before I developed Inherit.jl I had looked at Classes.jl. One of the issues was they used a parallel type hierarchy to what the user actually typed. It seems ObjectOriented.jl has a similar problem. Inherit.jl uses native Julia type hiearchy. _It introduces no new types._ There is no dispatch overhead at all.

This also restricts the current system from having multiple inheritance. MI will use parameterized container types and introduce the `<--` operator. But the main object hierarchy is still the Julia one. MI introduces Traits that decorates on this hierarchy.

---

<div class="post-metadata">

### Author: ![Kirby\_Zhang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kirby_zhang/32/36204_2.png) [@Kirby\_Zhang](https://discourse.julialang.org/u/Kirby_Zhang)
#### Post date: [May 19, 2023, 2:23pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/6 "2023-05-19T14:23:39Z")

</div>

Mixers.jl only inherit fields not interfaces.

---

<div class="post-metadata">

### Author: ![Kirby\_Zhang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kirby_zhang/32/36204_2.png) [@Kirby\_Zhang](https://discourse.julialang.org/u/Kirby_Zhang)
#### Post date: [May 19, 2023, 2:24pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/7 "2023-05-19T14:24:21Z")

</div>

Thanks. This has method signature verification. You can always dispatch to the signature you see.

---

<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 19, 2023, 4:37pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/8 "2023-05-19T16:37:58Z")

</div>

Sorry to be negative, there are a lot of attempts at these packages and mostly they don’t end up being used. I don’t users Mixers.jl at all. The solution ends up being _use composition_ 99% of the time.

I also couldn’t understand how you were enforcing interface compatibility, but I see that its using `eval` during ` __init__ `. That’s really discouraged from a precompilation standpoint these days. Maybe you could do it during precompilation?

---

<div class="post-metadata">

### Author: ![Kirby\_Zhang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kirby_zhang/32/36204_2.png) [@Kirby\_Zhang](https://discourse.julialang.org/u/Kirby_Zhang)
#### Post date: [May 19, 2023, 4:52pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/9 "2023-05-19T16:52:12Z")

</div>

Nothing wrong with negative feedback when it contains valid points.

Inheritance offers more natural, cleaner syntax than composition in many cases. It also naturally has zero dispatch overhead. It’s bad if not used well, but obviously no OOP package stops user from using composition.

I wouldn’t use Classes.jl or Mixers.jl myself. ObjectOriented.jl is newer and seems people are excited about it, but it sounds like some true use cases are not presented clearly.

Inherit.jl does several things practically:

- native Julia types, what you type is what becomes a Type.
- no dispatch overhead.
- guaranteed interfaces
- allows docstrings

It should be a lot closer to Java than Python mentally. Single inheritance, multiple interfaces (eventually when traits are implemented).

Another difference is being the latest OOP package, it relies on an important Julia 1.9 feature to allow you to evaluate a subtype in a supertype’s module context. So this would not have been possible pre 1.9. In fact after 1.9.0 was released I put more time into releasing the package, which I was developing under 1.9.0-RC2.

ps. The **init** it generates doesn’t do anything during precompilation. It only goes to work during runtime. Package level tests are included. With more users we can discover if there remains to be eval problems.

p.p.s there were several reasons to do verification during runtime, one of them was docstrings. But if eventually everything can be made to work during precompilation, that would actually be better.

---

<div class="post-metadata">

### Author: ![patrick-kidger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/patrick-kidger/32/20378_2.png) [@patrick-kidger](https://discourse.julialang.org/u/patrick-kidger)
#### Post date: [May 19, 2023, 5:12pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/10 "2023-05-19T17:12:59Z")

</div>

I like the look of this. Julia’s lack of enforcing interfaces is IMO one of its greatest obstacles to writing reliable code.

---

<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 19, 2023, 5:13pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/11 "2023-05-19T17:13:59Z")

</div>

Init actually is run during precompilation 😉

Putting code in init means longer load times if all interfaces need verification. Imagine something complicated like AbstractArray.

The interface idea is great (I had a go in Interfaces.jl) but Im not sure about runtime checks. You may as well do them in precompile if you have them in init.

You can generally define docs in your macros, although yes some things are difficult to generate if you e.g. need functions defined on the structs

---

<div class="post-metadata">

### Author: ![Kirby\_Zhang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kirby_zhang/32/36204_2.png) [@Kirby\_Zhang](https://discourse.julialang.org/u/Kirby_Zhang)
#### Post date: [May 19, 2023, 5:25pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/12 "2023-05-19T17:25:16Z")

</div>

To solve the loading time issue. You can `SkipInitCheck` globally, and change to `ThrowError` only during tests.

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [May 19, 2023, 5:35pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/13 "2023-05-19T17:35:04Z")

</div>

Would be nice to see a short example where benefits of this approach are highlighted, compared to regular Julia composition. Is it just the interface checking, or something else?

Trying to understand potential usecase, where/when should I reach for `Inherit.jl`?

---

<div class="post-metadata">

### Author: ![Kirby\_Zhang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kirby_zhang/32/36204_2.png) [@Kirby\_Zhang](https://discourse.julialang.org/u/Kirby_Zhang)
#### Post date: [May 19, 2023, 5:48pm UTC](https://discourse.julialang.org/t/inherit-jl/99102/14 "2023-05-19T17:48:08Z")

</div>

The doc right now is hosted on github (I’m not sure how to get it into Juliadocs): [Home · Inherit.jl (mind6.github.io)](https://mind6.github.io/Inherit.jl/). If you look at the Fruit, Berry, Apple, BlueBerry examples, composition would lead to less natural syntax and also make it hard to publish what the interface really is.

For me I use it when I’m repeating field definitions, or when it’s not clear which method calls are still valid on an object.

---

<div class="post-metadata">

### Author: ![TheLateKronos](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thelatekronos/32/12824_2.png) [@TheLateKronos](https://discourse.julialang.org/u/TheLateKronos)
#### Post date: [May 22, 2023, 6:35am UTC](https://discourse.julialang.org/t/inherit-jl/99102/15 "2023-05-22T06:35:28Z")

</div>

I for one do not actually know how to achieve this with “composition”, as some suggest. Could someone write up the example in the OP using composition?

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [May 22, 2023, 7:02am UTC](https://discourse.julialang.org/t/inherit-jl/99102/16 "2023-05-22T07:02:03Z")

</div>

So a problem is, artifial examples used for illustrating inheritiance work great.  
but that’s cos they are artificial, and so use things with strong “isa” relationships.  
“Is-a” relationships in practical code tend to actually be rare,  
and when they do occur often do not cooccur with having identical “hasa” relationships (i.e. fields) to the parent type.  
For example: `TreeDict` and `HashDict` both have an isa relationship with `Dict` but totally different set of fields.

Anyways we can write this code from the OP with composition if we like.  
It looks a bit clunky because it is.  
This is the code that is ideal for this kind of inheritiance – otherwise it would be poor to put in the example.  
It is just questionable how common this kind of code occurs in the wild.

```julia
abstract struct Fruit end
struct GenericFruit <: Fruit
	weight::Float64
end

cost(fruit::GenericFruit, unitprice::Float64) = fruit.weight * unitprice

struct Apple <: Fruit
    base::GenericFruit
	coresize::Int
end
# Convienience Constructor
Apple(weight, coresize) = Apple(GenericFruit(weight), coresize)

function cost(apple::Apple, unitprice::Float64)
    basecost = cost(apple.base, unitprice)
    return basecost * (apple.coresize < 5 ? 2.0 : 1.0) # small cored apples are 2x typical cost
end

```

Then we use test suites to check interaces

```julia
using Test
function test_interface(fruit::Fruit)
    @testset "Fruit Interface: $fruit" begin
        @testset "Must implement Cost" begin
            @test cost(fruit, 1.0) isa Any # make sure it doesn't error
            # But can test more sophisticated
            @test cost(fruit, 1.0) isa Real # check return type
            
            @test cost(fruit, 1.0) <= cost(fruit, 2.0) # Check monotonicity
            
            
            # Check linearity if that's wanted:
            @test iszero(cost(fruit, 0))
            @test cost(fruit, 1.0) + cost(fruit, 2.0) = cost(fruit, 3.0)
            @test 2*cost(fruit, 10.0) = cost(fruit, 20.0)
        end
    end
end

test_fruit(Apple(3.0, 4))
test_fruit(Apple(5.0, 1))

```

No criticsm to the OPs package.  
I am sure it does exactly what it sets out to do and is very useful in the circumstances where it is is useful.

---

<div class="post-metadata">

### Author: ![Kirby\_Zhang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kirby_zhang/32/36204_2.png) [@Kirby\_Zhang](https://discourse.julialang.org/u/Kirby_Zhang)
#### Post date: [May 22, 2023, 8:07am UTC](https://discourse.julialang.org/t/inherit-jl/99102/17 "2023-05-22T08:07:33Z")

</div>

We can try to build a collection of useful demo classes in future releases. Demo’s are not complete enough to warrant their own package, but have useful code and ideas in them. For example I have wanted to extend SparseMatrix without using composition which requires replicating the entire huge interface on matricies. Using Inherit most of the functionality can be in an @abstractbase, with simple end user concrete implementations that can be extended with just a few extra methods.
