4 ms·
I'm not sure what's the problem with setters? In my eyes, they are just a convenient shorthand for a common message. For example, Objective-C before version 2.0
by jakobegger 10y ago
I'm not sure what's the problem with setters? In my eyes, they are just a convenient shorthand for a common message. For example, Objective-C before version 2.0 didn't have setters; so the libraries had lots of methods like "setTitle:", "setDelegate:" etc. Setters are just a convenient shorthand. And in ObjC and in Swift (I don't know Java/C#/C++ so well) you can override setters to do whatever you like, so there really isn't much of a difference between using a setter and sending a message -- it's just syntactic sugar that makes code more readable.
- noblethrasher 10y agoBy “setter”, I mean a mechanism by which code that is external to an object can gain unmediated access to one or more of the object’s mutable instance variables. 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.
- probablybroken 10y agoIt sounds like you are referring to public properties.
- justincormack 10y agoIn languages like Lua you can always mediate what look syntactically like setters.
- DougBTX 10y agoAt least in C# terminology, a "setter" for a public property is mediated access, unmediated access would be a public field that can be set without invoking a setter method. 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.
- noblethrasher 10y agoAs it turns out, C# is a language that I know extremely well; I'm aware that setters can have arbitrary code. But, here's the problem: A programming a language is medium for thought, which means that it promotes or prevents the occurrence of certain ideas. 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.
- dragonwriter 10y agoBut classical setters aren't setters then, because the access is mediated (the are, or are backed by, methods which could do anything.) Only public fields provide unmediated access.
- noblethrasher 10y agoPlease see my reply to a sibling comment: https://news.ycombinator.com/item?id=14255796 https://news.ycombinator.com/item?id=14255796
- jwdunne 10y agoI think the problem is that, yeah, they're messages but very low level messages about the state of the object and not at all about a behaviour of the object in response to a message. 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.
- lacampbell 10y agoI think in those examples, there are probably smaller objects hiding inside your bigger objects, and you should construct them first. FYI ruby has named arguments since a few versions back.
- jwdunne 10y agoI think you're probably right. That's the ideal. 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.
- ZenPsycho 10y agoironically the "java/c#/c++"-ness in this case is precisely a point of difference with objective-c, which has messages, while java has only method invokations. meaning a setter in c++ is (more or less) syntactic sugar for setFoo(objectref, newval), while in objective-c it's more like sendMessage("setFoo",objectref, newval). 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?
- DougBTX 10y agoAn object that derives from DynamicObject in C# can have conditionals in its TryInvoke override, so it can change which method calls it responds to. However this sacrifices useful static compile-time checks, so it only gets used in unusual situations where the extra dynamic behaviour outweighs the cost. > 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.
- dkarl 10y agoThat's true, and often a well-designed object needs setters, but I think what the parent is getting at is using objects to model dumb data instead of behavior encapsulating state. If an object has getters and setters for all its members, then it isn't really an object. It's a degenerate object that is equivalent to naked data. Not much changes if it has only getters: then it's just immutable naked data. (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.)
- jfoutz 10y ago> If an object has getters and setters for all its members, then it isn't really an object. 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.