# Specialising behaviour of subtypes; methods or properties?

**URL:** <https://discourse.julialang.org/t/specialising-behaviour-of-subtypes-methods-or-properties/47907>\
**Category:** General Usage\
**Tags:** question, type\
**Created:** [October 7, 2020, 2:18am UTC](https://discourse.julialang.org/t/specialising-behaviour-of-subtypes-methods-or-properties/47907 "2020-10-07T02:18:27Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![timquelch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timquelch/32/18278_2.png) [@timquelch](https://discourse.julialang.org/u/timquelch)\
**Post date:** [October 7, 2020, 2:18am UTC](https://discourse.julialang.org/t/specialising-behaviour-of-subtypes-methods-or-properties/47907/1 "2020-10-07T02:18:27Z")

</div>

I’m developing a tree-like structure where each node can have children of different types. Some of the types of nodes are limited in the types and number of the nodes shown below.

```julia
abstract type Component end

struct ComponentA <: Component
    children::AbstractArray{Component,1}
    data::Int
end

struct ComponentB <: Component
    children::AbstractArray{Component,1}
    name::AbstractString
end

struct ComponentC <: Component
    child1::Component
    child2::Component
end

```

Most of the different types will have just a simple array of children components, so I can define a simple fallback method,

```julia
    children(x::Component) = x.children

```

However some like `ComponentC` above need a bit more specialisation. I’ve thought of two ways that I can do this

1. Define a new method for the types which require specialisation

2. Overload `getproperty` for those types so that the original  
`children` function works

I think I prefer 1 over 2, but I was wondering if there were any benefits either way. What are the pros and cons of each method? Is there a ‘correct’ way to do this?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 7, 2020, 6:19am UTC](https://discourse.julialang.org/t/specialising-behaviour-of-subtypes-methods-or-properties/47907/2 "2020-10-07T06:19:17Z")

</div>

Personally, I prefer the function approach, alternative 1.

The main difference is, I think, style, so it depends on what you prefer. Additionally, the property approach helps you with tab-completion, which is nice. But the function approach makes it more convenient to map over a collection, e.g.

```julia
children.(X)
# or
x |> foo |> children |> bar

```

instead of

```julia
getproperty.(X, :children)
# or 
x |> foo |> (v -> getprop(v, :children)) |> bar

```

You can of course do _both_.

I have some more remarks:

> [@timquelch](#):
>
> ```julia
> struct ComponentB <: Component
> children::AbstractArray{Component,1}
> name::AbstractString
> end
> 
> ```

For performance reasons, you should not use abstract types for the fields. Unlike in function signatures, this _does_ actually have an impact. Either use just

```julia
struct ComponentB <: Component
    children::Vector{Component}
    name::String
end

```

or parameterize the type to allow different array and string types (but for simple lists of components and names, I doubt this is useful.)

Also, here

> [@timquelch](#):
>
> `children(x::ComponentC) = Component[x.child1, x.child2]`

you are forcing the vector to have an abstract eltype, instead of just l allowing Julia to figure out the type automatically by writing

```julia
children(x::ComponentC) = [x.child1, x.child2] # no type specification

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [October 7, 2020, 11:12am UTC](https://discourse.julialang.org/t/specialising-behaviour-of-subtypes-methods-or-properties/47907/3 "2020-10-07T11:12:06Z")

</div>

> [@timquelch](#):
>
> Define a new method for the types which require specialisation

Yes, just do this. Generally, this is easier to extend, eg if you introduce a `ComponentD` that needs some other kind of specialization and lives in another package.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [October 7, 2020, 12:06pm UTC](https://discourse.julialang.org/t/specialising-behaviour-of-subtypes-methods-or-properties/47907/4 "2020-10-07T12:06:53Z")

</div>

Unrelated, but if possible [don’t use abstract types in fields](https://docs.julialang.org/en/v1/manual/performance-tips/#Type-declarations). If you make them `Vector{Component}` and `String` rather than `AbstractVector{Component}` and `AbstractString`, Julia will generate code that is faster, more compact, and more resistant to invalidation. This is true even though `Component` itself is abstract; `Vector{Component}` is a concrete type even though the elements are not.

---

<div class="post-metadata">

**Author:** ![timquelch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timquelch/32/18278_2.png) [@timquelch](https://discourse.julialang.org/u/timquelch)\
**Post date:** [October 8, 2020, 1:06am UTC](https://discourse.julialang.org/t/specialising-behaviour-of-subtypes-methods-or-properties/47907/5 "2020-10-08T01:06:26Z")

</div>

Wonderful, thanks for the help
