# How to enforce shared behavior for subtype constructors of abstract type

**URL:** <https://discourse.julialang.org/t/how-to-enforce-shared-behavior-for-subtype-constructors-of-abstract-type/52875>\
**Category:** General Usage\
**Created:** [January 5, 2021, 12:05pm UTC](https://discourse.julialang.org/t/how-to-enforce-shared-behavior-for-subtype-constructors-of-abstract-type/52875 "2021-01-05T12:05:33Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [January 5, 2021, 12:05pm UTC](https://discourse.julialang.org/t/how-to-enforce-shared-behavior-for-subtype-constructors-of-abstract-type/52875/1 "2021-01-05T12:05:34Z")

</div>

In Makie I have an abstract type `Layoutable`. Whenever a Layoutable is created with a `Figure` passed as the parent, I want the layoutable added to the figure’s children. The problem is that this behavior needs to happen in the constructor, which is unique for each struct. So I have no location where I can place a generic function that allows me to hook behavior into every `Layoutable` subtype.

Right now I’m doing this with a macro, so one has to create new `Layoutable` types via macro and the behavior I want is written into the inner constructor. Is there no better way to do this?

Usually the logic would be

```julia
function outer(x::Abstract)
    # do generic stuff before specific implementation, then
    specific_stuff(x)
    # do generic stuff after specific implementation
end

```

The problem is that for construction there is no `outer` shared by all subtypes, as it’s already given by each struct’s name. People will write `Button(...)`, `Legend(...)`, etc.

---

<div class="post-metadata">

**Author:** ![JonasIsensee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonasisensee/32/4704_2.png) [@JonasIsensee](https://discourse.julialang.org/u/JonasIsensee)\
**Post date:** [January 23, 2021, 1:37pm UTC](https://discourse.julialang.org/t/how-to-enforce-shared-behavior-for-subtype-constructors-of-abstract-type/52875/2 "2021-01-23T13:37:54Z")

</div>

hm, this seems indeed hard to do in general without a macro,  
since you definitely need to define a method for each type that dispatches to  
your outer constructor instead of the normal one.

This is the simplest thing that I could come up with,  
but of course that is brittle since it isn’t actually enforced.

```julia
struct Inner end

abstract type Layoutable end

struct Parent
    children
end

function Layoutable(::Type{T}, parent::Parent, args...; kwargs...) where T <: Layoutable
    # generic stuff

    child = T(Inner(), parent, args...; kwargs) # specific stuff

    push!(parent.children, child)
end

struct Button <: Layoutable
    x
    Button(::Inner, parent, x; kwargs...) = new(x)
end

Button(p::Parent, args...) = Layoutable(Button, p, args...)

p = Parent([])

b = Button(p, 42)

```

So the “agreement” would be to always forward the normal constructor to the abstract type first  
and via dispatching on a singleton `Inner` type you could then call the inner constructor.

---

<div class="post-metadata">

**Author:** ![piever](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/piever/32/1815_2.png) [@piever](https://discourse.julialang.org/u/piever)\
**Post date:** [January 23, 2021, 3:27pm UTC](https://discourse.julialang.org/t/how-to-enforce-shared-behavior-for-subtype-constructors-of-abstract-type/52875/3 "2021-01-23T15:27:02Z")

</div>

I’m not sure if this answers your question, but just from the point of view of dispatch you can do things like:

```julia
julia> abstract type Layoutable end

julia> struct Axis<:Layoutable
           label::String
           position::Float64
       end

julia> (::Type{T})(figure) where {T<:Layoutable} = T("x", 0.0)

julia> Axis(nothing)
Axis("x", 0.0)

```

This of course is a silly example, but I imagine something like

```julia
function (::Type{T})(figure) where {T<:Layoutable}
    # do generic stuff before specific implementation, then
    specific_stuff(T, figure)
    # do generic stuff after specific implementation
end

```

And then for every layoutable (e.g. `Axis`) you just overload `specif_stuff(::Type{Axis}, figure)`.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [January 23, 2021, 6:11pm UTC](https://discourse.julialang.org/t/how-to-enforce-shared-behavior-for-subtype-constructors-of-abstract-type/52875/4 "2021-01-23T18:11:42Z")

</div>

ah I didn’t think of dispatching on the constructor like that, I’ll have to think about if that can solve my problem cleanly

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [January 23, 2021, 9:50pm UTC](https://discourse.julialang.org/t/how-to-enforce-shared-behavior-for-subtype-constructors-of-abstract-type/52875/5 "2021-01-23T21:50:07Z")

</div>

This worked, my mistake was adding methods for the layoutables like `Legend(somearg, otherarg...)` directly, which doesn’t work together with a supertype intercept scheme like this. But changing all those methods to `layoutable(Type, somearg, otherarg...)` etc. and calling that from the abstract constructor works fine.
