inheritancejuliasubtyping

Julia Typing/Inheritance


Note: I found this post and read this part of Julia's documentation, but I couldn't figure it out yet. Therefore, I wrote this post.

Suppose we have the following two structs:

struct A
    x
end

struct B
    x
    y
end

whereby A is a generalization of B. Therefore, in other languages like Python or C++ I would make B inherit from A. Unfortunately, in Julia there is no inheritance, from my understanding so far. Please correct me if I'm wrong!

My Understanding About Abstract Types & Sybtyping in Julia, so far:

I just read about the concept of abstract types and subtyping in Julia. So far I've understood that I could do the following:

abstract type C end

struct A <: C
    x
end

struct B <: C
    x
    y
end

Hence, A and B are subtypes of C and the following holds:

(A <: C) == true
(B <: C) == true
(A <: B) == false
(B <: A) == false

Thus, I can't assign an instance of B to a variable of type A and vise versa.

Question:

Consider the first code example. Is it possible to make B "inherit" from A and to not define the field x in B again? Like I'd expect it from inheritance in other languages.

I hope my problem/question is clear, otherwise, please ask! Thanks for any hint/comment in advance! :)


Solution

  • Like I'd expect it from inheritance in other languages.

    No, it is not possible. Additionally, it is an intended design choice.

    In general in Julia the design follows Composition over inheritance principle.

    Therefore if you indeed want to use A in B then typically you would do:

    struct B
        a::A
        y
    end
    

    An alternative is to use an abstract upper type as you defined it:

    abstract type C end
    
    struct A <: C
        x
    end
    
    struct B <: C
        x
        y
    end
    

    And define an interface for C that requires all its subtypes to define x field, eg. like this:

    getx(::C) = throw(ArgumentError("subtypes of C must define getter of x"))
    getx(a::A) = a.x
    getx(b::b) = b.x
    

    In your simple case you also could just leave out defining anything, as the following code:

    f(c::C) = typeof(c.x)
    

    will work just fine (as long as all subtypes of C define property x - which should be clearly stated in the documentation of C that it is required).