Breako Breako
Breako Breako

Reputation: 6461

Make an object immutable at runtime

Is it possible in Groovy to make an object immutable at runtime? I know there is the immutable annotation but this works by only allow you create the object using a constructor and then never change it. I want something where I can create an object call 3 or 4 methods and then make it immutable so that it can never be changed again?

Any ideas on how to do this?

Thanks.

Upvotes: 3

Views: 295

Answers (2)

tim_yates
tim_yates

Reputation: 171094

I don't believe you can. You could probably remove the setters via the meta class, but you would struggle to make the fields final, and collections would need to be changed to immutable variants.

As of Groovy 2.2.1, you have the copyWith addition to Immutable... Maybe this can help?

import groovy.transform.*

@Immutable( copyWith=true )
class Test {
    String name
    int age
    List likes
}

def alice = new Test( 'alice', 26, [ 'cheese' ] )
tim = alice.copyWith( name:'tim', age:32 )
timHam = tim.copyWith( likes:[ 'ham' ] )

assert alice.name == 'alice' && alice.age == 26  && alice.likes == [ 'cheese' ]
assert tim.name == 'tim'     && tim.age == 32    && tim.likes == [ 'cheese' ]
assert timHam.name == 'tim'  && timHam.age == 32 && timHam.likes == [ 'ham' ]

There's also this Immutator package for Java which looks interesting, but I couldn't get it to work in the Groovy console... Might be worth seeing if it works in a regular groovy context with packages, etc

Upvotes: 3

Seagull
Seagull

Reputation: 13859

If you want an Immutable object, and want to call some methods before (for configuration purposes?) it may be good to look at Builder Effective Java Joshua Bloch (page 11). It's a class, wich you can create to configure your object, and then get an immutable instance of it.

Also, I have checked reflexion approach, but it looks like you can't restrict field access via it.

Upvotes: 0

Related Questions