# Defining a subclass

**URL:** <https://discourse.julialang.org/t/defining-a-subclass/80716>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 8, 2022, 5:06pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716 "2022-05-08T17:06:41Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 8, 2022, 5:06pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/1 "2022-05-08T17:06:41Z")

</div>

I realise this is a newbie question, but I think it’s sort of central to the whole Julia ethos. I really like the idea of moving away from object-orientation’s emphasis on single dispatch, and that lattices of types perform a lot of the work of subclassing. And I quite see it makes sense that you can’t derive from a concrete type. And yet I’ve come to a point where I don’t really understand how to proceed.

I want to create a type `State` that is essentially a `Vector{Complex}`, but I want to give it extra constraints like maybe the sum of all components must always be equal to 1. Normally, in the object-riented world, I’d do this by subclassing and providing constructors and operations that preserve the constraint. But of course, in Julia, I can’t derive from `Vector{Complex}`. I could say `State` is a `struct` that contains a `Vector{Complex}`, but then I’d have to relay all existing Vector functionality from the field to the `struct`. The simplest idea seems to be to declare them equal:

`State = Vector{Complex}`

But then how do I create `State`s? Julia won’t let me declare a `State()` constructor. I could create a method `state()` that creates `State`s that fulfil the necessary constraints, but that seems a cheat. As far as I can see, I’m missing something essential about the Julia model here, but I don’t know what it is, and I’d love for someone to tell me.

Thanks.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [May 8, 2022, 5:29pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/2 "2022-05-08T17:29:33Z")

</div>

Hi @Niall !  
I think one way to solve your problem is to define a `State` struct that is a subtype of `AbstractVector{Complex}`.  
Since `Vector{Complex}` is a concrete type, you cannot directly subtype it. However, you can make your struct usable as an abstract array simply by defining [a few methods](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array).

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 8, 2022, 5:41pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/3 "2022-05-08T17:41:31Z")

</div>

Thanks. So I’d wrap the `Vector{Complex}` inside a `State`, then map `size()`, `getindex()` and `setindex()` from the `State` to the wrapped `Vector{Complex}`, yes? To me, that sort of feels a little clumsy, isn’t it?

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 8, 2022, 5:53pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/4 "2022-05-08T17:53:55Z")

</div>

I’m terribly sorry, @gdalle, I didn’t mean your idea was clumsy - I meant the necessity of doing it seems unnecessarily clumsy.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 8, 2022, 6:00pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/5 "2022-05-08T18:00:49Z")

</div>

There are packages to simplify this, e.g. [GitHub - JeffreySarnoff/TypedDelegation.jl: Easily apply functions onto fields' values. Use a struct's fields as operands for operations on values of that type.](https://github.com/JeffreySarnoff/TypedDelegation.jl)

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [May 8, 2022, 6:37pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/6 "2022-05-08T18:37:16Z")

</div>

No worries! In my opinion that would be the julianic way, but there are probably simpler alternatives. Like if you only need checks when constructing a state, maybe you could make do with a `get_state` function that returns a `Vector{Complex}`?

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 8, 2022, 6:50pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/7 "2022-05-08T18:50:33Z")

</div>

OK, so assuming you’re correct (that it is the Julian way), then this is a clear statement that having to delegate methods from wrapper to field is definitely preferable to subclassing from a struct. I can see that subclassing leads to changes in memory allocation that would hit performance, but it doesn’t seem to me that that problem would be insurmountable. Is there some other reason why delegation is to be preferred?

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [May 8, 2022, 7:03pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/8 "2022-05-08T19:03:05Z")

</div>

First of all I’m not 100% confident that I’m right about this ^^  
Regarding your latest question, I’m not sure what you mean by “subclassing from a struct”. In Julia it is only possible to define children of [abstract types](https://docs.julialang.org/en/v1/manual/types/#man-abstract-types), not structs

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [May 8, 2022, 7:12pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/9 "2022-05-08T19:12:02Z")

</div>

Just an offtopic remark. The reason why this is the Julian way is that it gives you access to all the methods that operate on the types of objects you created, from any package that defined any method that can operate on the supertype you subtyped. For example, if you create a simple wrapper for a vector:

```julia
julia> struct A{T} <: AbstractVector{T}
           x::Vector{T}
       end

julia> Base.length(a::A) = length(a.x)

julia> Base.size(a::A) = size(a.x)

julia> Base.setindex(a::A,i) = setindex(a.x,i)

julia> Base.getindex(a::A,i) = getindex(a.x,i)

```

Then suddenly all the functions that work on vectors work for your type:

```julia
julia> a = A([1,2,3,4])
4-element A{Int64}:
 1
 2
 3
 4

julia> mean(a)
2.5

julia> dot(a,a)
30

julia> a + a
4-element Vector{Int64}:
 2
 4
 6
 8

julia> a * a'
4×4 Matrix{Int64}:
 1 2 3 4
 2 4 6 8
 3 6 9 12
 4 8 12 16

```

but you can also overload any of them if you want them to have a different meaning (only do this for the types you have defined, otherwise is type-piracy):

```julia
julia> import Base: +

julia> +(a::A,b::A) = a - b
+ (generic function with 319 methods)

julia> a + a
4-element Vector{Int64}:
 0
 0
 0
 0

```

Even the functions invented for your new type after your type was defined will work. That is, once you do the clumsy work of defining the necessary wrapper functions, the whole Julia ecosystem will be available to work on your types, not only a subset of functions that where defined specifically for the original supertype by some particular implementation of it.

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 9, 2022, 10:34am UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/10 "2022-05-09T10:34:30Z")

</div>

Not at all offtopic - thanks very much to you both. I do indeed understand that I can’t subtype from structs. I teach programming, and in relation to that I wanted to pinpoint precisely why that is the case. My current thinking is this …

I think it was precisely the very simplicity of my current situation (i.e.: wrapping a Vector simply in order to place a mathematical constraint on its elements) that made me wonder for the first time whether I’d got it right. If the AbstractVector interface were more method-rich, wrapping might become significantly more effort than being able to subclass Vector{Complex}, and that made me think about whether there might be more to the julian ban on subtyping structs than met the eye.

However, it seems that there isn’t, and I think probably my simple situation would be the exception rather than the usual case.

Thanks and best wishes,

Niall.

---

<div class="post-metadata">

**Author:** ![hexaeder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hexaeder/32/24403_2.png) [@hexaeder](https://discourse.julialang.org/u/hexaeder)\
**Post date:** [May 9, 2022, 11:07am UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/11 "2022-05-09T11:07:02Z")

</div>

To my understanding, the (admittedly sometimes annoying) property, that each concrete type is also final (can’t be subtyped) enables a lot of the nice features of Juila, because it allows the compiler reason about the memory layout of variables based on their runtime-type.

For example, I can define composite types

```julia
struct Foo
    x::Float64
    y::Float64
end

struct Bar
    f::Foo
end

```

where both `Foo` and `Bar` are bit types, which means they have a fixed size in memory. It would not be possible for `Bar` to be a bit type if `f::Foo` might represent a subtype `MyFoo <: Foo`. In that case `f` would be a pointer rather than inlined memory . Forbidding this leads to nice things, such as arrays `Vector{Foo}` and `Vector{Bar}` which are continuous in memory and just consist of tightly packed `Float64` bit-sequences.

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 9, 2022, 11:09am UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/12 "2022-05-09T11:09:28Z")

</div>

Ah wait - I’ve just realised what it was that set me wondering. In my code I had simply set:

`State = Vector{Complex}`

and it surprised me that I couldn’t write a new, additional, constructor for it - I really do think that would be useful. However, it would then also be a new constructor of Vector{Complex}, and I realise that could bring its own problems. 🙂

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [May 9, 2022, 12:28pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/13 "2022-05-09T12:28:44Z")

</div>

There are already good advices for the OP’s question here, but I think it’s also worth to ask: is a new type really needed?

If the goal is to define a constructor of a vector that complies some constraint, well, constructors are just functions, so you can just define a function that returns a “normal” `Vector{Complex}` enforcing the target constraint.

If it is important to ensure that `x::State` always complies that constraint, even if some modification to the wrapped vector is attempted, just defining a new type is not sufficient. Some function `checkconstraint(::State)` would be needed at some point to throw an error whenever an “illegal” modification is attempted, and a generic function `checkconstraint(::AbstractVector)` could be made instead, so that it can be applied to normal vectors too.

From my point of view, the main reason to make a `State` type that just wraps a vector of complex numbers with some constraint, is to be able to distinguish between such `State`s and “unwrapped” vectors that happen to meet the constraint. For instance: if there is some function that should _only_ work for `State`s and not for other vectors, or if you want a function to do different things if they are applied to `State` vectors, so that you can take advantage of multiple dispatch (e.g. if the sum of two `State` vectors must transform the result so that it also meets the constraint).

Otherwise, perhaps you can just stick to `Vector{Complex}`, and save the trouble of adapting the `AbstractVector` interface to a new type. The idea of using an alias `State = Vector{Complex}` is good to simplify the code, but then you should choose another name for the “constructor” function (e.g. `state`, in lowercase).

As an aside, maybe what you might want to wrap/alias is not `Vector{Complex}`, but `Vector{<:Complex}`, which is a more generic type:

```julia
julia> Vector{Complex} <: Vector{<:Complex}
true

julia> Vector{<:Complex} <: Vector{Complex}
false

```

(The difference is that if `typeof(x) <: Vector{Complex}`, then `eltype(x) == Complex`; whereas if `typeof(x) <: Vector{<:Complex}`, then `eltype(x) <: Complex` – i.e. `eltype(x)` _can_ be the abstract type `Complex`, but also any of its subtypes.)

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 9, 2022, 2:49pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/14 "2022-05-09T14:49:58Z")

</div>

Thank you - yes that makes perfect sense.

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 9, 2022, 2:58pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/15 "2022-05-09T14:58:02Z")

</div>

I like your point here - particularly in combination with @hexaeder’s above. I do indeed want to maintain the constraint (these States are in fact quantum States with |s|=1), and the sum of two States must also satisfy the constraint. So I definitely want to create a new type, and so need to delegate. The notation `Vector{<:Complex}` is new to me - I’m just not sure what it would bring me, since `Complex` doesn’t (can’t) have any subtypes. What am I missing?

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [May 9, 2022, 4:05pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/16 "2022-05-09T16:05:54Z")

</div>

> [@Niall](#):
>
> The notation `Vector{<:Complex}` is new to me - I’m just not sure what it would bring me, since `Complex` doesn’t (can’t) have any subtypes. What am I missing?

Sorry, I didn’t use the correct words: `Complex` is not an abstract type, but it is a _parametric_ type. That means that it is not either a concrete type, as you can see when you create actual complex numbers:

```julia
julia> typeof(1+1im)
Complex{Int64}

julia> typeof(1.0 + 1.0im)
ComplexF64 (alias for Complex{Float64})

```

None of them is “just” `Complex`: the concrete types also carry information of the type of numbers contained (real and imaginary parts).

Now, about the notation `Vector{<:Complex}`, the first few posts of the following discussion can help you (the discussion is about the abstract type `Number`, not about the parametric type `Complex`, but the situation is analogous):

> [@Why \[1, 2, 3\] is not a Vector{Number}?](https://discourse.julialang.org/t/why-1-2-3-is-not-a-vector-number/52645):
>
> I don’t understand this: julia\> isa([1,2,3], Vector{Number}) false Each 1, 2, or 3 is certainly a Number: julia\> isa(1, Number) true It is illogical to say [1, 2, 3] is not Vector{Number} when each element is a Number.

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 9, 2022, 4:18pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/17 "2022-05-09T16:18:14Z")

</div>

Great - thanks very much! 😁

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [May 9, 2022, 7:47pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/18 "2022-05-09T19:47:58Z")

</div>

> [@Niall](#):
>
> these States are in fact quantum States with |s|=1

By the way, perhaps the things you need are already available in packages:  
[https://docs.qojulia.org/](https://docs.qojulia.org/)

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 10, 2022, 7:49am UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/19 "2022-05-10T07:49:28Z")

</div>

Thanks, but I’m teaching this, so I’m trying to set up a Julia environment in which students learn programming through building precisely this kind of code for themselves. However, I’ll certainly take a look at qojulia - it looks interesting.

Best wishes,

Niall.

---

<div class="post-metadata">

**Author:** ![Niall](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niall/32/22517_2.png) [@Niall](https://discourse.julialang.org/u/Niall)\
**Post date:** [May 19, 2022, 2:07pm UTC](https://discourse.julialang.org/t/defining-a-subclass/80716/20 "2022-05-19T14:07:18Z")

</div>

As an afternote to this thread: I’ve since realised that my OO hankering to derive State from Vector was wrong-headed. A State really isn’t a Vector, but rather delegates certain functionalities to a Vector. I actually suspect that is quite generally the case. Thank-you Julia for the insight! 😀
