ilPittiz
ilPittiz

Reputation: 754

Override DefaultGroovyMethods method

Is there a way to easily override toSet(Collection<T> self) method from DefaultGroovyMethods?
Its implementation uses HashMap

public static <T> Set<T> toSet(Collection<T> self) {
    Set<T> answer = new HashSet<T>(self.size());
    answer.addAll(self);
    return answer;
}

but I’d like to use a LinkedHashMap to preserve the order of elements in the argument collection.

I tried with metaprogramming (already used a few times in various custom classes), e.g.

Collection.metaClass.toSet = {
    println 'in'
    Collection self = (Collection) delegate
    Set<Collection> answer = new LinkedHashSet<Collection>(self.size())
    answer.addAll(self)
    return answer
}

but with no luck (cannot enter that closure).
Any suggestion will be very welcome. Thanks is advance!

ps: I'm currently developing a Grails 4.0.3 app, Groovy 2.5.6

Upvotes: 1

Views: 254

Answers (1)

Szymon Stepniak
Szymon Stepniak

Reputation: 42184

You can override this method using Groovy extensions module. It works fine in a regular Groovy code, but it should also work when used with Grails framework. Consider the following example:

package com.example

import groovy.transform.CompileStatic

@CompileStatic
class MyDefaultGroovyMethods {

    static <T> Set<T>  toSet(final Collection<T> self) {
        final Set<T> set = new LinkedHashSet<T>(self.size())
        set.addAll(self)
        return set
    }
}

You can register this helper method to override a Collection.toSet() method by creating a following src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule file:

moduleName = my-default-groovy-methods-module
moduleVersion = 1.0
extensionClasses = com.example.MyDefaultGroovyMethods

Then you can test it with something like this:

def xs = [1,3,2,4]

def set =  xs.toSet()

println xs.toSorted()

println set

println set.class

Output:

[1, 2, 3, 4]
[1, 3, 2, 4]
class java.util.LinkedHashSet

Upvotes: 4

Related Questions