views:

120

answers:

7

So, I'm normally a ruby programmer, so my grasp of Java conventions is shaky at best. If I have a class A and want to define a method to add two instances of that class, what's the convention on the behaviour and return type?

public class A
{
    //...
    public NotSureWhatTypeItShouldReturn add (A that) { /* ... */ }

Should I

  • return a boolean indicating success and modify the target, or
  • return a modified copy of the target and throw an exception on error

Which fits with the normal Java convention for this kind of method?

+1  A: 

I would recommend the same behaviour as in Collection.add, this is what I would expect.

stacker
A: 

From the Java Collections API:

Ensures that this collection contains the specified element (optional operation). Returns true if this collection changed as a result of the call. (Returns false if this collection does not permit duplicates and already contains the specified element.)

Collections that support this operation may place limitations on what elements may be added to this collection. In particular, some collections will refuse to add null elements, and others will impose restrictions on the type of elements that may be added. Collection classes should clearly specify in their documentation any restrictions on what elements may be added.

If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an exception (rather than returning false). This preserves the invariant that a collection always contains the specified element after this call returns.

MikeD
A: 

This is not really a convention, but only what boolean Collection<E>.add(E) exemplifies:

Returns: true if this collection changed as a result of the call
Throws: UnsupportedOperationException - if the add operation is not supported by this collection

Methods of the Java Collections Framework classes rarely returns the collection that they're invoked upon. That is, it's not idiomatic to support this:

mySet.add(thisThing).add(thatThing).add(thoseAlso);

Some classes in the Java libraries employ the "fluid" style, e.g. Appendable such as StringBuilder, but none of the main Java Collections Framework classes do.

polygenelubricants
+6  A: 

Both exist: Collection.add modifies the collection and returns a boolean, and BigInteger.add returns a new BigInteger that holds the sum of the original and the passed-in instance.

I generally expect most methods to modify the instance they're being called on, rather than returning a new object of the same type, but if there's a good use case for keeping instances const and returning a new instance all the time you can certainly do that

Michael Mrozek
+1, for mentioning adding numbers. OP never said he was adding to a collection of things ;)
FrustratedWithFormsDesigner
+5  A: 

Don't return a boolean unless it's an "expected failure" e.g. trying to add to a set. If something actually goes wrong, throw an exception.

Now, you could return a modified copy - or you could add to the existing object. Immutability is often a nice property... but most collections in Java are mutable. If you're going down the immutable route you might want to consider using plus instead of add - it gives more of a feeling of "there's a result you should look at, and I won't change the target" IMO.

Jon Skeet
A: 

Depends on the semantic of your class, but typically it would be:

public void add( A that ) {
} 

If what you intend is just to aggregate elements.

You can use:

public boolean add( A that ) {
}

If your intention is to know if the structure was modified or not ( Like with a java.util.Set or collections in general )

And you can use public A add( A that ){} if your intention is to create a "builder like" object ( just like StringBuilder.append method.

 A a = new A();
 a.add( a ).add( b ).add( c ).build();

So depending on the semantic of your class you could use either.

Most of the times (+90%) I do the first: void add( A other ){}

OscarRyz
+3  A: 

Everyone here is thinking about Collections.add()-type method; but I doubt that's what you're thinking. Are you more in the line of, say, Vector2D.add() which adds the x and y component of the Vector2D together?

In Java, as far as I can tell, Collections generally modify themselves (and so does Collections.add).

However, non-Collections object (e.g. Vector2D) varies more. Among the conventions I've seen:

  1. Cls add(Cls b) which returns a new object and does not modify existing instances
  2. void add(Cls b) which modifies this and returns nothing (i.e. returns void), it should not modify b. There is no point in returning bool since this type of addition is never supposed to fail (and if it does anyway, an Exception would be appropriate).
  3. Cls add(Cls a, Cls b) which returns a new object, modifies neither a nor b. Cls.add() is a static method in Cls class.

Personally, I prefer the first style for arithmetic-style add(); precisely because we can do a.add(b).add(c).add(d) which looks a bit like "a + b + c + d". (I wouldn't normally do this if a is a Collection; since serial addition looks weird for Collections object.)

Lie Ryan
I would agree, implement your objects as immutables, and using your Vector2d example:Vector2d a = new Vector(1,2);Vector2d b = new Vector(3,4);Vector2d c = a.add(b);//a = (1,2)//b = (3,4)//c = (4,6)
gregcase