the difference might seem minor but the extra layer of inderection means the target object can have centralised logic to handle the outcome of this message if it wamts to, as opposed to repeating and distributing such logic among every method, making it a more independent unit as opposed to something being directly manipulated from the outside.
put another way, the object can decide independently what to do with the message "setFoo" in objective C (or ruby), but in c++ there is no message, no decision, just some code that directly causes something to happen, that can be invoked directly from any other part of the program ar any time, whose results are then relied upon to be visible directly after invokation.
as a thought experiment, imagine if the target object actually exists on a different server, what would the different unsugared implementations need to look like? how would you pause the in progress program to wait for the result of the method invokation? what impact might that delay have on the user?
> whose results are then relied upon to be visible directly after invokation
I'm not sure I buy that, surely those details are down to the individual methods in question. There's lots of hairy (distributed) COM code out there that doesn't make that promise for example, and it won't hold in a multi-threaded environment for objects that are not explicitly thread-safe in any case.
The big idea is that the sender should not be able to assume that the message, `setFoo`, will have any particular effect with respect to the reciever’s state.
Getters and setters in C# are method calls, like `setFoo` in Java, so can't be assumed to be simple, they can do anything any other method can do.
So, even though the compiler will accept any legal void-returning code within the inner braces of
public Foo Bar
{
set
{
//Do stuff
}
}
The fact that the client code is going to look like `Obj.Foo = whatever` will practically foreclose on all but a small subset of possibilities.Only public fields provide unmediated access.
I think, however, they're a good way of building objects where a language lacks object or hashmap shorthand (e.g JS and Ruby). In fact, with Obj-C, if my memory serves right, it can look just as expressive.
Setters (particularly fluent), in that case, seem best for building objects in a readable way where a language lacks a way to pass express keyword arguments.
FYI ruby has named arguments since a few versions back.
Thanks for letting me know - can't believe I missed that. I don't use Ruby professionally, just as a scripting language to make my life at work easier.
(Which I think is a good thing, and I hate it when people make blanket assumptions otherwise! And I hate it when languages like Java make it awkward to express dumb immutable data. I think the pieces in a program that are best modeled as "behavior" and "state" is a subset, usually a proper one, often a small one, of the data and functionality that needs to be modeled in a nontrivial program. Often there's a lot of data in a program that is most clearly modeled as dumb data, or at least as transparent data packaged together with some common operations. "Behavior" and "state" is mental overhead that only pays for itself when you have to express a certain amount of complexity. That's why it's so important for a language to let you start in one style, with plain transparent data (and lots of immutability), and switch to encapsulated behavior when you discover that part of the code is complex enough to benefit from it. Otherwise you pay a high mental cost to future-proofing every piece of data with getters and setters and private data when it's possible that only a small portion of your code will ever benefit from it.)
Minor quibble. Take for example a coordinate class, that you can get/set cartesian, and get/set polar. It's a nice example of an object with no private state, but transparently hides the coordinate system transformations.
In general, i agree with you. The vast majority are just (possibly immutable) structs.