views:

502

answers:

5

I've been thinking of ways of providing syntactic sugar for a framework I have been working on. I want to deal with Immitable objects exclusively.

Say I have an immutable object and wish to create a modified version of it. Would, in your view, a non-instantiable class with a single static factory method break OO principles ?


As an example using a String:

public final class LOWERCASE {

    private LOWERCASE() {}

    public static String string( final String STRING ) {

      return STRING.toLowerCase();
    }
}

Therefore from this example I could write:

String lowercaseString = LOWERCASE.string( targetString );

Which I find very readable.


Any provisos against such an approach?

+1  A: 

Usually on immutable objects, I would have a method returning a modified version of the object. So if you have some immutable collection, it can have a sort() method, that returns a new collection that is sorted. However, in your String example this is not possible, since you cannot touch the String class.

Your approach is quite readable, and I think for edge cases like this, is perfectly fine. For immutable objects you write yourself, I'd have the method on the object itself.

Eric Lippert's series on immutable objects in C# is quite good, by the way.

Erik Hesselink
+4  A: 

I don't think it's a good idea to create one class per method. You could instead create a static only methods class, named e.g StringUtils and implement the methods. This way you would call:

String lowerCaseString = StringUtils.lowercase( targetString );

This would also offer you intellisense help while you are typing. The list of your classes will go otherwise too big. Even for this simple example, you should implement more than one Lowercase classes, so that you could also cater for circumstances that the CulutureInfo must be taken into consideration.

I don't think this breaks OO principles in any way or that is bad design. In other languages, Ruby for example, you could add your methods directly to String class. Methods that end with ! denote that the original object is modified. All other methods return a modified copy. Ruby on Rails framework adds some methods to the String class and there is some debate about whether this is a good technique or not. It is definitely handy though.

kgiannakakis
+1  A: 

In my opinion, the only point of such a factory class would be if the class provided different kinds of immutable objects.

Ex:

public final class Lowercase {

  private Lowercase() {}

  public static String string( final String string ) {

   return new String( string.toLowerCase() );
  }

  public static Foo foo( final Foo f ) {
     boolean isLowerCase = true;
     return new Foo(f, isLowerCase );
  }
}

Otherwise, you should implement your method in the immutable class itself like toLowerCase() in String Class.

Either way, I don't think this breaks any OO principle.

bruno conde
+1  A: 

I agree with Erik. Immutable objects should always have a method returning a modified version of the object rather than a static method. There are also examples in the JDK:

  • String.subString(int)
  • BigDecimal.movePointLeft(int)

Doing it this way has the advantage that you don't need to pass the instance you want to modify as argument for a method. For classes like String or Integer I would prefer to use a wrapper class. Then you can control when such an object is created (by constructor of the wrapper class or one of the methods of the class). If you would use the class Integer it is much more complicated to control this as everyone can create an instance of it.

On the other hand you're example is regarded to some utility classes like StringUtils of the apache commons-lang package. Just have a look at this as I think that you wanted to create something like this. (Don't reinvent the wheel)

reallyinsane
+1  A: 

new String() is a code smell - it is almost always unnecessary because of the immutability of String. Once a String instance has a value, that instance will never, ever have a different value.

In the following method, new String() is redundant:

public static String string( final String string ) {
    return new String( string.toLowerCase() );
}

toLowerCase() returns a new (different) String instance - new String() doesn't do anything beneficial here other than cause another object creation having the exact value of the String instance returned by toLowerCase()

Here's a small Groovy script showing the concept (I hope - note, this is Java under the scripting language):

String a = 'CamelCase'
String b = a.toLowerCase()

println "a='${a}'"
println "b='${b}'"

producing

a='CamelCase'
b='camelcase'

Note that a didn't change - it is immutable; b is a new String value.

The same is true for BigDecimal.movePointLeft() or any other method on BigDecimal that returns a BigDecimal - they're new instances, leaving the original instance unchanged.

OK, now to answer your question:

Having a set of operations for Strings that perform a useful purpose in your application is a fine idea. Using a factory probably isn't necessary for something like String, but might be for a different immutable class that takes some effort to construct.

In the case where it is not possible to extend the base class, like String, a static methods class as @kgiannakakis described is fine.

Otherwise, if the "immutable" class is part of the application, where you have access to the class declaration/definition, methods returning a new instance, in the model of BigDecimal, String, etc, would be preferable. This is in essence what @Erik Hesselink ,@Bruno Conde and @reallyinsane have said.

Ken Gentle
+1 for "don't use new String()"
matt b