groovy

Enum does not support instance (value) specific methods

Details

  • Type: Sub-task Sub-task
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Fixed
  • Affects Version/s: None
  • Fix Version/s: 1.7-rc-1
  • Component/s: None
  • Labels:
    None
  • Testcase included:
    yes
  • Number of attachments :
    1

Description

Java enum allows instance (value) specific methods. Groovy does not support this currently. The following code fails in Groovy (compilation error):

class GroovyEnumRangeTest extends GroovyTestCase {
void testEnumMethod()

{ assertEquals "Work", Day.MONDAY.activity() assertEquals "Relax", Day.SUNDAY.activity() }

}

enum Day {
SUNDAY {
String activity() { 'Relax' }
}, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY

String activity() { 'Work' }
}

If I need it right now, I am able to use EMC to achieve this:

class GroovyEnumRangeTest extends GroovyTestCase
{
void testEnumMethod()
{
def emc = new ExpandoMetaClass(Day)
emc.activity = {-> 'Relax' }
emc.initialize()

Day.SUNDAY.metaClass = emc
assertEquals "Work", Day.MONDAY.activity()
assertEquals "Relax", Day.SUNDAY.activity()
assertEquals "Work", Day.TUESDAY.activity()
}
}

enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY

String activity() { 'Work' }
}

so it is not major (IMHO).

Issue Links

Activity

Hide
Chris Currivan added a comment -

The documentation suggests that this isn't a useful feature. Here's an example where I'm using it in Java, but can't port directly to Groovy. I wrote a lexer where I use enums as the token definitions, each with its own regex passed to the constructor. Each enum has its own onMatch method to do something specific with the regex capture groups.

Another workaround instead of ExpandoMetaClass is to pass a closure with an explicit this parameter, and curry it with the instance's this parameter which is visible in the constructor

 
enum Foo {
    Add(1, {_this, y -> _this.x + y }),
    Mult(100, {_this, y -> _this.x * y })
    Foo(int x, Closure c) {
      this.x = x
      func = c.curry(this)
    }
    final Closure func
    int x
}

import static Foo.*

println Add.func(10)
println Mult.func(10)
Show
Chris Currivan added a comment - The documentation suggests that this isn't a useful feature. Here's an example where I'm using it in Java, but can't port directly to Groovy. I wrote a lexer where I use enums as the token definitions, each with its own regex passed to the constructor. Each enum has its own onMatch method to do something specific with the regex capture groups. Another workaround instead of ExpandoMetaClass is to pass a closure with an explicit this parameter, and curry it with the instance's this parameter which is visible in the constructor
 
enum Foo {
    Add(1, {_this, y -> _this.x + y }),
    Mult(100, {_this, y -> _this.x * y })
    Foo(int x, Closure c) {
      this.x = x
      func = c.curry(this)
    }
    final Closure func
    int x
}

import static Foo.*

println Add.func(10)
println Mult.func(10)
Hide
blackdrag blackdrag added a comment -

implemented

Show
blackdrag blackdrag added a comment - implemented
Hide
Roshan Dawrani added a comment -

Jochen, regarding checking in EnumVisitor whether InnerClassNode represents an anonymous inner class or not - is it correct to check it using the following check - "ic.getVariableScope()==null"?

During the compilation, VariableScopeVisitor visits after EnumVisitor and currently the only place where InnerClassNode#setVariableScope() gets called is in VariableScopeVisitor - which means that EnumVisitor will always see ic.getVariableScope() as null and hence assume every InnerClassNode to represent AIC. It is creating a regression issue where nested enums are getting affected.

Is there an alternative way of determining whether InnerClassNode represents an anonymous inner class or not?

Show
Roshan Dawrani added a comment - Jochen, regarding checking in EnumVisitor whether InnerClassNode represents an anonymous inner class or not - is it correct to check it using the following check - "ic.getVariableScope()==null"? During the compilation, VariableScopeVisitor visits after EnumVisitor and currently the only place where InnerClassNode#setVariableScope() gets called is in VariableScopeVisitor - which means that EnumVisitor will always see ic.getVariableScope() as null and hence assume every InnerClassNode to represent AIC. It is creating a regression issue where nested enums are getting affected. Is there an alternative way of determining whether InnerClassNode represents an anonymous inner class or not?
Hide
Roshan Dawrani added a comment -
Show
Roshan Dawrani added a comment - Jochen, what do you think about this one? It is affecting nested enums (GROOVY-3979) - http://groups.google.com.sg/group/groovy-user/browse_thread/thread/02fcdc8753f38d8b/0b73b8a6f95bdb1e?show_docid=0b73b8a6f95bdb1e

People

Vote (3)
Watch (3)

Dates

  • Created:
    Updated:
    Resolved: