Hugo Firth
Hugo Firth

Reputation: 535

Setting a Field vs. Creating a new Object

I was reading an article earlier when I cam across the following quote from Alan Kay:

"Lots of so called object oriented languages have setters and when you have an setter on an object you turned it back into a data structure."

The article went on to imply that this was not best practice and could hurt applications you develop in the long run.

I'm a CompSci student with experience with C, Java, PHP, Ruby etc... so am fairly familiar with OOP as a concept and a practice, but am by no means an expert.

I guess what my question boils down to is this:

Is it semantically correct (and a matter of best practice) when writing OO programs, to access field values (with getters) and then Create new Objects based upon the modified values RATHER than using setter methods to simply adjust the field of that object.

Or if have a piece of wood, and I then carve some wood off of that original piece, should I model that as the same piece with less mass, or a new piece entirely.

Using setters appears to be more concise and Garbage collection would be an issue if you were creating so many objects so I am approaching this question from a theoretical, rather than practical, viewpoint.

Thanks in advance for your answers!

Upvotes: 1

Views: 3074

Answers (7)

supercat
supercat

Reputation: 81149

Suppose some variable foo identifies a class object with some field bar, and presently foo.bar=5;. One would like for foo.bar to equal six. Your question is whether it is better to have foo continue to identify the same object, but change that object's bar to six, or whether it's better to have foo identify a new object which is just like the one it used to identify except that its bar field will equal 6. In cases where both approaches would be correct, modifying the field (whether directly or through a setFoo() call) is apt to be more efficient than creating the new object, and would thus be "better". Often, however, only one of the approaches will be correct; the other won't simply be "not as good"--it will be wrong.

The $50,000 question in determining which approach to use is what is supposed to be encapsulated by foo and the object identified thereby.

  • If foo holds a reference to a shared object, and other references to it use it to encapsulate the a state where "bar=5", then modifying bar would be wrong. The only correct approach is to create a new object, and change foo to identify that instead of the original.

  • If foo holds the only reference anywhere in the universe that identifies a particular object, then the creation of a new object or the modification of the existing object would be semantically equivalent, though as noted modifying the existing object is apt to be faster.

  • If foo identifies an object to which other references exist, and its purpose is to identify the object which is identified by those other references (effectively forming a connection with those other references), then changing foo to identify a different object would be wrong unless all references to that object are updated to identify the new object instead.

  • If field bar is final, or is otherwise protected against modification, then even if one holds the only reference to a particular object, there's no alternative but to create a new object and make foo identify it.

The second case and fourth cases are perhaps the most common; those could be handled by the principle "Don't create new objects needlessly" [in case 2, new object creation can be avoided; in case 4, it can't]. That principle will also easily handle case 3 [since it would encourage one do to the necessary thing]. The only problematic case from the perspective of that rule is the first. Even there, the key is recognizing that creation of the new object will be necessary if the reference is shared but is not intended to encapsulate identity.

I suspect one of the real reasons behind the popularity of immutable objects is that proper use of mutable objects requires knowing which references should encapsulate identity and which ones don't; use of immutable classes allows one to dodge such issues.

Upvotes: 0

user1342582
user1342582

Reputation:

An object must have at least one of two types of responsibilities: behaviour and knowledge. Behaviour defines how the object reacts to events within its execution context, and knowledge defines what the object knows.

Behaviour is implemented as methods where the method names map onto the events that trigger reactions. Knowledge is implemented as getters that return values mapping to the knoweldge being queried.

Designed and implemented in this way, objects rarely need setters, as object states change only in reaction to external events. Having said this, one may implement an external event as a setter (e.g. car.setSpeed(...)), but usually a more suitable name should be sought (e.g. car.accelerateTo(...) and car.decelerateTo(...)).

Upvotes: 2

JB Nizet
JB Nizet

Reputation: 691715

It's a matter of design. The basic principle of OO is encapsulation. Suppose you have a Circle object. You could have a setter for the radius and a setter for the perimeter. But of course, since both are linked together, setting the perimeter should also change the radius, and setting the radius should also change the perimeter. If that's not the case, you indeed don't have an object anymore, but a simple data structure, without any encapsulation.

Now some objects are mutable, and some others are not. For example, a String or an Integer is immutable. Once it has a value, its value can't change. Concatenating a String to another one just creates a new String instance, without affecting any of the two original Strings. Immutable objects are easier to understand and use, because they only have one state. They also are inherently thread-safe. But they can lead to performance problems. For example, concatenating in a loop creates a whole lot of temporary String instances that consume memory and must be GC'ed. That's the reason why StringBuilder exists: it's basically a mutable String.

To conclude: there is no definitive answer, because it all depends on the kind of object, and the way it's used. In general, favor immutable objects over mutable ones. Favor less mutable objects over more mutable ones.

Upvotes: 1

user1219266
user1219266

Reputation:

setters can expose your inner implementation and cause some problems. if you set an object, and perform some actions based on the new assignment state, it might cause a problem if the assigned object is changed externally.

Upvotes: 0

brimborium
brimborium

Reputation: 9512

This completely depends on what you want to achieve. If you want to change the properties of an instance, you should use setter or similar methods (carveOutSomeWood()). If you need to have access to the previous version and want to generate a new instance, you can implement some sort of createCopy()/clone() method to create a copy and then apply carveOutSomeWood() to that new instance.

I would not reccommend creating a new instance by reading out properties of the old instance and creating it by yourself. The main reason (there might be others) is, that your class might change. You would then also have to change your creation of the new instance, as it is done outside of the class. If you simply use a createCopy() method it would be in the responsibility of the class to account for its changes.

You can also directly introduce an derive() method which creates a copy internally and applies some changes.

Upvotes: 0

biril
biril

Reputation: 1995

In my opinion it all depends on whether you model the object in question as 'immutable'. This might make perfect sense depending on your model and in this case you should refrain from coding setter methods.

Generally speaking though, I find no reason for not using setters. Besides, you can find many languages (C#, AS3) which provide specialized syntax for defining setter methods.

Upvotes: 0

Attila
Attila

Reputation: 28762

You are asking two questions:

1) Is it OK to have public fields in an object?

It is usually better from a maintenance/debugging perspective if you access fields of objects via methods for at least one reason: the method introduces a common entry for change to the field, and you can add custom logic to prevent invalid changes or update the invariant of the object to keep its state consistent with the requested change. If you have no internal state in the object, you don't need a method (but it's still advisable: it introduces a single breakpoint area for all accesses for debugging)

2) Should I use mutable or immutable objects?

Either approach is correct. Immutable objects allow easier reasoning on the code as you cannot modify the state of existing objects. OTOH you can end up with a lot more objects, so either will use more memory or the garbage collector will have more work. Mutable object offer the opposite advantages/disadvantages

Upvotes: 0

Related Questions