Re: Kinds of methods




"Daniel T." <postmaster@xxxxxxxxxxxxx> wrote in message news:postmaster-1C277D.17060822032006@xxxxxxxxxxxxxxxxxxxxxxxxxx
In article <sFhUf.203$B_1.47@edtnps89>,
"Oliver Wong" <owong@xxxxxxxxxxxxxx> wrote:

A setter method modifies the apparent (or external) state of the object
which owns that method. A mutator changes the apparent state of the object
which you pass in, but not of the object owning the mutator. E.g.

"Foo.setX(bar)" would change the state of Foo (perhaps depending on the
state of bar), while "Foo.mutateX(bar)" would change the state of bar
(perhaps depending on the state of Foo).

So what is the logical difference between:

class Foo {
public:
void mutateX( Bar& bar ) const;
Bar getBar() const;
Bar factoryBar() const;
};

Bar bar;
foo.mutateX( bar );

and

Bar bar = foo.getBar();

In both cases, some object external to foo is getting mutated, and the
'bar' object's state will be a direct result of foo's state.

To me, there is no indication that bar is mutated in the call foo.getBar(). Also, there is some sort of association or relation between bar and foo in the second case (with the getter), which is not present in the first case (with the mutator).

With mutators, conceptually, you could have passed in any bar, and the mutator would have done whatever it has to do. With the getter, the bar you're talking about is "special" to foo. bar might be linked to foo (e.g. foo observes bar or the other way around), such that foo reacts to events that occur on bar.



What's the difference between:

Bar bar = foo.getBar();

and

Bar bar = foo.factoryBar();

In both cases, the member-function is returning a new object initialized
by the foo object and assigned to bar...

Same as above, I suppose. With a getter, the bar has a "belongs-to" relationship with foo. With the factory, the bar is yours.


I call all three member-functions producers. They all set up an object's
state based on the state of the object being called.

Yes, there are similarities, and there are differences. If the intent is to assign a categorize these methods in terms of their behaviour, I claim that there are cases where you may be interested in whether the return value is part of the object's state, or whether it's an independent thing being created for your consumption, for example.

A getter method gives the caller access to the apparent state of the
object, while a factory "creates" (or returns handles to already existing)
objects which are not part of the state of the object.

OK, so a method is a factory if the state of the object it is called on
is irrelevant? I wouldn't call that a factory, I would call that a
mistake. Why is the method a member function if the object it is called
on doesn't figure into what the function does?

I guess we're getting into the semantics of "state", and whether it can be said an immutable object has state. I was thinking something like a GUIWidgetFactory class, of which you might have an instance called linuxWidgetFactory, another called macWidgetFactory, and yet another called windowsWidgetFactory. From the outside view, these instances don't have any state, put at the implementation, they obviously have to keep track of what kind of widgets they have to create.

Anyway, methods on these instances like "makeRadioButton()", "makeDropDownMenu()", etc. don't depend on the APPARENT state of the objects, but they of coruse depend on the internal, implementation state (e.g. it determines whether an instance of GnomeDropDownMenu is returned, or an instance of WinXPDropDownMenu).

For example, if you had a random number generator, and you called the
"GetNextRandomInteger()" method, conceptually, this is a factory method, in
that what it returns is not supposed to be related to the state of the
random number generator at all (in practice, most RNGs are actually
pseudo-RNGs, and so they DO have state, and their output IS dependent on the
state).

Again, seems to me that GetNextRandomInteger shouldn't be a
member-function if the output has nothing to do with the state of the
object it is called on... Maybe I'm missing something?

The (pseudo-)RNG might have been obtained via a factory method like this:

getRNG(seed);

Now whether the seed is part of the internal state of the RNG or not is an implementation detail, and therefore plays no part in the apparent state of the RNG. Seemingly, GetNextRandomInteger is creating integers out of the blue, with no dependence on any apparent state at all.

>> But then there are functions which just return a value based on its
>> inputs,
>> without setting, getting, making, or mutating anything. E.g.
>>
>> number function double(number n) {
>> return n * 2;
>> }
>
> The above is a producer, it creates an object.

Hmm... what about the concept of a pure function, in the mathematical
sense? That is, a mapping from a domain to a range? Is that "creating"
objects, or is it "getting" states, or something else?

We aren't talking about pure math, we're talking about OOP. In every OOP
language that I know, a function either creates an object or modifies
one.

What about this method, in Java?

public void doNothing() {
return;
}

In math terms, it maps elements from the empty set onto elements in the empty set.

>> And then there are functions which produce side-effects in the system,
>> without affecting the objects themselves. E.g.
>>
>> console.write("Hello World!");
>>
>> I guess you could argue that this write() method is affecting the >> state
>> of
>> the conceptual console (of which the console object is acting as a >> proxy
>> for), but then you'd have these "black hole setters", where you're
>> setting
>> some state which you can never actually retrieve again.
>
> I would indeed argue that, and I see no problem with "black hole
> setters".

The problem with "black hole setters" is that the state you're setting
is not external or apparent, and so there's a lost of 1-to-1 association
between setters and getters.

I don't think there needs to be a 1 to 1 association between setters and
getters. In fact, I prefer not to make such an association...

class Foo {
public:
void mouseClickAt( int x, int y );
void keyHit( char k );
};

I see nothing wrong with the interface above despite it's lack of
accessors that are directly related to either of the member-functions. I
could see adding some sort of "getState" member-function for testing
purposes but there still isn't a one-to-one association.

I might be missing something, and I still have to digest HS's post...

It's not clear to me how to use your Foo class. Am I suppose to call its methods, or subclass it? It looks like it might be some sort of "EventListening" interface that I'd have interested classes implement, and then pass on to other objects, but the interface itself doesn't define at all what the behaviour of the implementations might be when the interesting events occur.

That is, I'd implement the interface, and then hope, somewhere down the road, someone else will call these methods to let me know what's going on. And since the interface doesn't make it clear what is SUPPOSED to happen when these methods get called, it's difficult to classify them as being "setters" or "mutators" or something else.

- Oliver

.


Quantcast