# Extending \`getproperty\`

**URL:** <https://discourse.julialang.org/t/extending-getproperty/53728>\
**Category:** New to Julia\
**Created:** [January 21, 2021, 2:47pm UTC](https://discourse.julialang.org/t/extending-getproperty/53728 "2021-01-21T14:47:09Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![circonflexe](https://avatars.discourse-cdn.com/v4/letter/c/c57346/32.png) [@circonflexe](https://discourse.julialang.org/u/circonflexe)\
**Post date:** [January 21, 2021, 2:47pm UTC](https://discourse.julialang.org/t/extending-getproperty/53728/1 "2021-01-21T14:47:09Z")

</div>

So I want to extend `getproperty` (and likewise `setproperty!`) for a custom type, a bit like what `LinearAlgebra.LU` does. I see that this is usually done with an `if/else` chain; however, this is not very Julian in style, and moreover I would like to keep the list open if possible, and to do this for a lot of types without copying too much boilerplate code.

So I came up with the following solution, which allows me to add a custom property to a custom type in a one-liner if needed, at the cost of inserting some `Val`.

```julia
@inline getproperty(x, s::Symbol) = _getproperty(x, Val(s)) # <- ☠ type piracy, arrh!
@inline _getproperty(x, ::Val{S}) where{S} = Base.getfield(x, S)

# ...
function _getproperty(x::MyType, ::Val{:myfield})
  #...
end

```

The two first lines ensure that, for types for which I do not define `_getproperty`, this will be equivalent to the definition in `Base.jl`.

Is there anything wrong with this solution (apart from style points lost for type piracy)? Is there a special case which I missed? Will this compile to hundreds of specialized functions, or will it all be silently inlined? Are the `@inline` macros even useful here? Will this also work for `setproperty!`? Would it be better if I wrote a big `@generated` function looking if a method exist for `_getproperty`?

---

<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:** [January 21, 2021, 2:56pm UTC](https://discourse.julialang.org/t/extending-getproperty/53728/2 "2021-01-21T14:56:45Z")

</div>

Is there something in the example provided in the help of getproperty that does not work for you?

```julia
help?> getproperty
search: getproperty

  getproperty(value, name::Symbol)

  The syntax a.b calls getproperty(a, :b).

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> struct MyType
             x
         end
  
  julia> function Base.getproperty(obj::MyType, sym::Symbol)
             if sym === :special
                 return obj.x + 1
             else # fallback to getfield
                 return getfield(obj, sym)
             end
         end
  
  julia> obj = MyType(1);
  
  julia> obj.special
  2
  
  julia> obj.x
  1

```

---

<div class="post-metadata">

**Author:** ![jonniedie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jonniedie/32/12842_2.png) [@jonniedie](https://discourse.julialang.org/u/jonniedie)\
**Post date:** [January 21, 2021, 3:38pm UTC](https://discourse.julialang.org/t/extending-getproperty/53728/3 "2021-01-21T15:38:37Z")

</div>

Well, you wouldn’t want to do it in a type-pirated way like that, but doing this same thing for specific types of `x` is somewhat common. So like make your original `getproperty` a method for `x::MyType` directly, not just for generic `x`. At least that’s what I do for `ComponentArrays`, but also with a `@generated` function for `_getproperty`. It seems to work better than anything else I tried. But there are a bunch of reasons you might want to use a `@generated` function. And also keep in mind that doing the `Val` thing can really slow things down if the compiler isn’t able to do constant propagation. Usually it’s fine for `getproperty` though.
