Naming convention for accessor methods (get/set)

  • Thread starter Generic Usenet Account
  • Start date
G

Glen Low

This naming convention is also consistent with the IDL/C++ language
binding, and I wanted to seek your opinion regarding this.

C++ iostreams uses the int xyz(); void xyz(int) convention as well.

What is so evil about accessors/mutators, if they are not "just"
returning the underlying data member? (They could be calculating it,
caching it or passing it on to another object for example.)

Here's a suggestion to make the accessor/mutator pair into a first
class object, akin (but better in the long run) to VB/C# property,
your thots please.

We define a property class (with appropriate templating) to declare:

property& operator= (T);
operator T() const;

The signature is the same or similar to the proxy objects that often
crop up in delayed dereferencing scenarios.

The class contains a reference to the underlying object, and two PMFs
(either as template non-type params or constructor params) to the
[private] accessor/mutators in the object.

The object can either expose the property as a public data member (I'm
going to get into trouble for this one...), or through a member
function.

The former allows you to do this:
a.xyz = 12; std::cout << a.xyz;

The latter is slightly clunkier:
a.xyz() = 12; std::cout << a.xyz();

If the latter, a compiler would probably just optimize away the
property temporary anyway. (The latter also allows indexing
scenarios.)

What else does this buy you? The property can now be used as an
object, a substitute for a reference e.g.

template <typename U> void mul (U& z, const U& x, const U& y) { z = x
* y; }

Now mul could only take U = int before. But it can now take a property
and it will do the right thing. A bit similar to how an STL iterator
is an extension of the pointer, the property is like an extension to
reference. mul would not work with the pair of accessor/mutator
unwrapped.

Any comments, caveats, thoughts on this?

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com
 
S

Shay

Glen Low wrote:
[snip]
Here's a suggestion to make the accessor/mutator pair into a first
class object, akin (but better in the long run) to VB/C# property,
your thots please.

We define a property class (with appropriate templating) to
declare:

property& operator= (T);
operator T() const;

The signature is the same or similar to the proxy objects that
often crop up in delayed dereferencing scenarios.

The class contains a reference to the underlying object, and two
PMFs (either as template non-type params or constructor params) to
the [private] accessor/mutators in the object.

The object can either expose the property as a public data member
(I'm going to get into trouble for this one...), or through a
member function.

Exposing a member doesn't have to constrain the enclosing class at all:

class X {
X( X const& );
X& operator = ( X const& );
void operator & () const;
// anything else I left out :)
};

class Foo {
public:
X x; // what does this expose other than Foo having an X named x?
};
What else does this buy you? The property can now be used as an
object, a substitute for a reference e.g.

template <typename U> void mul (U& z, const U& x, const U& y) { z =
x * y; }

Now mul could only take U = int before. But it can now take a
property and it will do the right thing. A bit similar to how an
STL iterator is an extension of the pointer, the property is like
an extension to reference. mul would not work with the pair of
accessor/mutator unwrapped.

With properties added to the mix, a class could be seen as a collection of
members, each with a particular interface. A data member is an entity
which stores a value and allows access to it. A member function is an
entity which has an operator () and implements it via its definition, or
via the virtual dispatch mechanism. A value property is an entity which
acts like a value but implements get and set via function call rather than
by-value storage within itself.

This value property allows accessible abstract state to be expressed more
directly, and manipulated using the already-existing mechanisms for values
(as your example shows). At the core of this is the recognition that a
class is a collection of interface elements, and we can start thinking of
expansion of the usual set.

I described this value property in a way that I hope hints at further
possibilities. One is backwards-compatibility with overloaded accessor
functions that it might have replaced: a value property can define
operator () () as a getter and operator () ( value_type ) as a setter.
There could be a "cached value property" which keeps a copy of its value
and gives this out when it is read, and when it is written, only invokes
the "set new value" callback if the new value is different than the old
one.

It's also possible to go beyond values. How about a readable boolean flag
with an optional callback that is invoked when it changes value? This
property would keep track of the current value, allow reading of this, and
allow registration of a callback function. The enclosing class would keep
this flag up-to-date, but wouldn't have to bother with the callback. The
property would have public functions and "parent-only" functions that were
only accessible to the enclosing class (here there would be a parent-only
function to change the flag's value).

How about a counted entry/exit with parent notification on first
entry/last exit? Here the property stores the entry count, has member
functions entry() and exit(), and two callbacks to the parent,
first_entry() and last_exit().

I've done a little experimentation with data providers and consumers. I
made a supplier and consumer property. It uses an intrusive circular
doubly-linked "ring" and traversed it when the provider had a new value. A
class might supply many different values, so each one could be a separate
property.

A property could be thought of as being just like a base class, except
that its interface isn't injected into the parent class but rather appears
as part of the interface of a member of the parent class. The parent class
can override "virtual" functions in the property and gets special access
like a derived class can.

Properties have two clients: general clients and the parent class. I think
of the electronics field where there are user-interface devices which have
internals and an interface to the device. Think of a simple toggle switch:
It has a button that the user can press (the public interface), two wires
which are either electrically open or closed (the parent-only interface),
and a mechanism to keep the current open/closed state latched and toggle
it when the button is pressed. Without property elements, the engineer's
equivalent would be mounting the toggle switch inside the device and
running a long mechanical bar from the button to the case (i.e. connect
the button's interface to the public via a member function).

A fine point I encountered in various implementations: with the
introduction of property values, the value type might differ from the
object type. An int stores an int, but a value_property<int> doesn't store
a value_property said:
::type both yielded int. This allowed simple scoped value restoration
which worked for any value type.

I've implemented several very crude libraries for experimentation with
properties over the years. I implemented quite a few properties in various
classes (file streams, audio output, GUI controls) but never really found
much use for them. Because I had the possibility of implementing ideas of
new properties, I was open to places to add them, but very few ideas ever
came. I'd be interested in brainstorming places where they might be
useful, then looking critically or even trying it out. I think that the
ability to do hands-on experiments is very important for growing and even
the abandoning of ideas. I have a feeling that the property idea might not
be viable, but I want to see it demonstrated. I'm not content with
reasoning it away, because most reasoning I've encountered seemed aimed at
avoiding the possibility of something new rather than making insights as
to the flaws.
 
J

Jerry Coffin

[ ... ]
We define a property class (with appropriate templating) to declare:

property& operator= (T);
operator T() const;

The signature is the same or similar to the proxy objects that often
crop up in delayed dereferencing scenarios.

This was suggested in a rather lengthy thread years ago in comp.std.c++.
Feel free to read through the thread starting at:

http://www.google.com/[email protected]

for various views on the subject.
The object can either expose the property as a public data member (I'm
going to get into trouble for this one...), or through a member
function.

IMO, in a situation like this, the member function provides no real
capabilities to compensate for the obfuscation.
 
G

Glen Low

With properties added to the mix, a class could be seen as a collection of
members, each with a particular interface. A data member is an entity
which stores a value and allows access to it. A member function is an
entity which has an operator () and implements it via its definition, or
via the virtual dispatch mechanism.

That last one is an interesting observation. We could implement a
"member function" in terms of a data member, which is a STL-style
functor or function class. This may have some advantages, like being
able to say that it is a unary_function or binary_function or keep
state.
It's also possible to go beyond values. How about a readable boolean flag
with an optional callback that is invoked when it changes value? This
property would keep track of the current value, allow reading of this, and
allow registration of a callback function. The enclosing class would keep
this flag up-to-date, but wouldn't have to bother with the callback. The
property would have public functions and "parent-only" functions that were
only accessible to the enclosing class (here there would be a parent-only
function to change the flag's value).

I was experimenting with something similar, tying an event
notification mechanism with properties. Either subject/observer
patterns are too general i.e. notify me of any change (GoF) or not
tied to specific objects (WFC, .NET, most Microsoft technologies). If
the event notification mechanism were tied to a singly-typed property
object, we could arrive at self-calculating or self-updating objects
e.g. a C++ spreadsheet-like object.

It would be even cooler to declare in C++:

A = B + C;

where B and C are properties with events, and A is another property,
and the overloads actually cause A's value to be updated with B's
value + C's value.
A property could be thought of as being just like a base class, except
that its interface isn't injected into the parent class but rather appears
as part of the interface of a member of the parent class. The parent class
can override "virtual" functions in the property and gets special access
like a derived class can.

The approach I took was: if the get/set needs to be changed, it is
changed via the original virtual function on the declaring object.
This means that you can simply inherit the base object and not have to
simultaneously inherit/fiddle around with the base object properties.
I've implemented several very crude libraries for experimentation with
properties over the years. I implemented quite a few properties in various
classes (file streams, audio output, GUI controls) but never really found
much use for them. Because I had the possibility of implementing ideas of
new properties, I was open to places to add them, but very few ideas ever
came. I'd be interested in brainstorming places where they might be
useful, then looking critically or even trying it out.

The main use of it for me, at least initially, was to objectify C APIs
that used opaque types e.g.

SetWindowVisible (win, show);
if (GetWindowVisible (win)) { ... }

becomes:

win.Visibile = show;
if (win.Visibile) { ... }

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com
 
G

Glen Low

Do also note there's nothing necessarily tying a property to a single
declaring object. A property is just an abstraction of access, and in
that way it could actually relate to many objects, or to no objects.

For example, we could define a "property" to abstract access to the
equivalent property on a set of objects. Setting the property causes
the equivalent property on each object to be set. Getting the property
fetches the property value from the first object in the set and.or
determines whether all the values are the same etc.

If we keep generic code that uses the properties agnostic as to the
underlying object(s), if any, I believe we'll get much more functional
code.

Cheers,
Glen Low, Pixelglow Software
www.pixelglow.com
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top