I am trying to add Base.property
methods to my own types for the first time and hitting a wall. Here’s a minimal example:
module A
import Base.getproperty
struct S
x
end
Base.getproperty(x::S, ::Val{:a}) = "a"
end
obj = A.S(1)
obj.a
This gives the error:
ERROR: type S has no field a
Stacktrace:
[1] getproperty(::Any, ::Symbol) at ./sysimg.jl:18
I am on Julia 1.0.1 on OSX. Thanks for any suggestions.
2 Likes
julia> struct S
x
end
julia> function Base.getproperty(x::S, sym::Symbol)
if sym == :a
"a"
else
# fallback to getfield
getfield(x, sym)
end
end
julia> obj = S(1)
S(1)
julia> obj.a
"a"
julia> obj.x
1
julia> obj.y
ERROR: type S has no field y
Stacktrace:
[1] getproperty(::S, ::Symbol) at ./REPL[2]:6
4 Likes
(Note that due to ongoing GitHub issues, you may see that link as a 404—I do.)
You can still dispatch on the property name with
_getproperty(x::S, ::Val{s}) where {s} = getfield(x, s)
_getproperty(x::S, ::Val{:a}) = "a"
Base.getproperty(x::S, s::Symbol) = _getproperty(x, Val{s}())
However, you should only do this if you have a small number of property names, as there’s lots of potential for performance issues. It’s also a good idea to provide methods for Base.propertynames
.
3 Likes
Thank you for the solution. Is this the intended way to use Base.getproperty
or a workaround for a current issue? I would have had a hard time figuring this out from the docs. If it’s intended, I’ll submit a PR for the Julia docs.
It is the intended way, cf
help?> getproperty
search: getproperty
getproperty(value, name::Symbol)
The syntax a.b calls getproperty(a, :b).
See also propertynames and setproperty!.
3 Likes