Recommended way of implementing getters and setters

1,020 views
Skip to first unread message

Adriano Vilela Barbosa

unread,
Jul 29, 2015, 11:59:57 PM7/29/15
to julia-users
Hi,

This question is about programming style. I would like to know what's the recommended way of writing getters and setters in Julia.

I have a TimeSignal class written in Matlab that I'm trying to port over to Julia. In the Matlab implementation, I have some getter methods for computing the values of the dependent properties (e.g., the number of samples "n_samples", the associated time vector "time_vector", etc.). My question is: what's the recommended way of implementing these getter functions in Julia? Maybe implementing a getindex() function so that I can do, for example, time_signal[:n_samples]? Or is it better to explicitly write getter functions like get_n_samples(time_signal), get_time_vector(time_signal), etc?

I read the thread about dot overloading at

https://github.com/JuliaLang/julia/issues/1974

but this still seems to be an open issue at the moment.

Thanks a lot,

Adriano

Tomas Lycken

unread,
Jul 30, 2015, 2:21:51 AM7/30/15
to julia-users
For getters, I would opt for the latter approach with methods which you call on the time signal. However, I would also encourage you to extend already existing functions rather than creating new ones. For example, you could get the number of samples as Base.length(ts::TimeSignal). Sometimes it may make sense to provide more than one argument to these functions.

For setters, I'd do the same thing where it makes sense, but make sure to follow the convention that the function name ends with a bang (!) and that the time signal is the first argument, eg det stuff!(ts::TimeSignal, stuff...)

Good luck!

Adriano Vilela Barbosa

unread,
Jul 30, 2015, 10:50:02 AM7/30/15
to julia-users, tomas....@gmail.com
Thanks for your answer.

Before posting my original question, I took a look at some packages listed in

http://pkg.julialang.org/

just to see what people were doing. I didn't notice much of a pattern, and that's why I decided to ask here.

For example, the package PySide (https://github.com/jverzani/PySide.jl) offers both interfaces, so that it's possible to do either

w = Qt.QWidget()        # constructors
w[:setWindowTitle]("Hello world example") # w.setWindowTitle() is w[:setWindowTitle] in PyCall

or

w = Widget()
setWindowTitle(w, "Hello world example (redux)") # methodName(object, args...)

At the end of that page, the author talks about "generic methods" such as get_value() and set_value(), which makes me wonder if he's thinking of things like

get_value(obj,property_name)

and

set_value(obj,property_name,property_value)

Maybe in the end it's just a matter of personal preference, at least for now.

Thanks a lot.

Adriano

j verzani

unread,
Jul 30, 2015, 11:34:58 AM7/30/15
to julia-users, tomas....@gmail.com, adriano...@gmail.com
That's maybe not the best package to look at for examples. It was written quite awhile ago (and doesn't get any use as far as I can tell). The `get_value` is "generic" in the sense that the "main" property for different widgets might have different property names and this function would just look it up based on the type of the widget.

As for your original question, the use of indexing by symbols is inherited from PyCall, and is only there because the "dot" isn't available. I don't think it makes a good interface. It is awkward to type for starters. The advice to use Julia's generic concepts, as possible, is a good one. An example there would be the interface for Gtk through Gtk.jl.

Adriano Vilela Barbosa

unread,
Jul 30, 2015, 4:13:02 PM7/30/15
to julia-users, tomas....@gmail.com, jver...@gmail.com
I see. I looked at PySide.jl because I use Qt quite a bit in Python (though, for historical reasons, I use PyQt instead of PySide).

I had a look at Gtk.jl and noticed that they use getproperty() and setproperty!() a lot. For example:

setproperty!(win, :title, "New title")

getproperty(win, :title, String)

I guess this makes sense for a GUI toolkit where objects have lots of properties. In my case, I think it makes more sense to do things like (I dropped the "get_" prefix from the getter methods)

n_samples(time_signal)
time_vector(time_signal)

instead of

get(time_signal,:n_samples)
get(time_signal,:time_vector)

Hopefully, I'm in the right direction here and using "Julia's generic concepts". Not sure exactly what you mean by that...

Thanks a lot,

Adriano

Kristoffer Carlsson

unread,
Jul 30, 2015, 4:25:37 PM7/30/15
to julia-users, tomas....@gmail.com, jver...@gmail.com, adriano...@gmail.com
When I name my getters like that I always run into the problem that I want to do:

n_samples = n_samples(time_signal).

Adriano Vilela Barbosa

unread,
Jul 30, 2015, 4:50:09 PM7/30/15
to julia-users, tomas....@gmail.com, jver...@gmail.com, kcarl...@gmail.com
I know exactly what you're talking about; I'm having the same problem.

I thought that maybe I shouldn't use a variable n_samples in the first place and simply do n_samples(time_signal) whenever I need to query the number of samples in the signal. However, this is annoying, and sometimes we do want to store the returned value in some other variable (maybe, for example, because the getter method has to do some expensive computation and we don't want to run it every time we query the property).

What are you doing in your case? Maybe adding a "get" prefix to your getter methods?

Adriano

Jeffrey Sarnoff

unread,
Jul 30, 2015, 6:26:51 PM7/30/15
to julia-users, tomas....@gmail.com, jver...@gmail.com, kcarl...@gmail.com, adriano...@gmail.com
this is possible:

```
julia> typealias TimeSignal Array{Float64,1}
Array{Float64,1}

julia> type Sampler
          signal::TimeSignal
       end

julia> function call(x::Sampler)
           x.signal
       end
call (generic function with 1125 methods)

julia> function call(x::Sampler, y::TimeSignal) 
           x.signal = y
           x
       end
call (generic function with 1125 methods)

julia> time_signal_A = convert(TimeSignal, [0.2,0.3,0.8]);

julia> time_signal_B = convert(TimeSignal, [0.3,0.2,0.6]);

julia> # intialize your sample
       sample = Sampler(time_signal_A);

julia> # get it, scale it down as a new sample
       scaled = Sampler( sample() .* 0.5 )
Sampler([0.1,0.15,0.4])

julia> # (re)set it
       sample(time_signal_B)
Sampler([0.3,0.2,0.6])

```
Reply all
Reply to author
Forward
0 new messages