I have been going through the Programming Scala book(by Martin Odersky,Lex Spoon,Bill Venners ed1) and came across traits. A section that I find interesting is stackable modifications. The example used is
abstract class IntQueue {
def get(): Int
def put(x: Int)
}
trait Incrementing extends IntQueue {
abstract override def put(x: Int) {super.put(x+1)}
}
trait Filtering extends IntQueue{
abstract override def put(x: Int){
if(x >=0) super.put(x)
}
}
so the example provided has a concrete class "BasicIntQueue that extends IntQueue as follows
import scala.collection.mutable.ArrayBuffer
class BasicIntQueue extends IntQueue{
private val buf = new ArrayBuffer[Int]
def get() = buf.remove(0)
def put(x: Int) {buf +=x}
}
scala> val queue = (new BasicIntQueue with Incrementing with Filtering)
scala> queue.put(-1);queue.put(0);queue.put(1)
scala> queue.get() = 1
So the example shows that both the filtering and incrementing are "chained" and executed before the elements are "put" into the queue.
I was just wondering how this could be accomplished in Groovy. Maybe it is not needed because of Groovy's meta-programability.
Beginning from Groovy 2.3 Groovy supports traits and also stackable traits. The implementation looks therefore exactly as in Scala:
interface IntQueue {
Integer get()
void put(Integer x)
}
trait Incrementing implements IntQueue {
void put(Integer x) { super.put(x+1) }
}
trait Filtering implements IntQueue {
void put(Integer x) { if(x >= 0) super.put(x) }
}
class BasicIntQueue implements IntQueue {
private buf = new ArrayList<Integer>()
Integer get() { buf.remove(0) }
void put(Integer x) { buf << x}
String toString() { buf.toString() }
}
def queue = new BasicIntQueue().withTraits Incrementing, Filtering
queue.put(-1)
queue.put(0)
queue.put(1)
assert queue.get() == 1
Groovy doesn't have a natural way to do stackable traits. Categories provide some of the trait functionality, but they're not well suited to overriding methods and can't be stacked without much metaclass magic.
A better approach in groovy would be to apply the decorator pattern along with the #Delegate annotation. Each "trait" can override the appropriate behavior and delegate to the "super" class. Example:
interface IntQueue {
def get()
def put(x)
}
class Incrementing implements IntQueue {
#Delegate IntQueue self
def put(x) {
self.put(x+1)
}
}
class Filtering implements IntQueue {
#Delegate IntQueue self
def put(x) {
if (x >= 0) {
self.put(x)
}
}
}
class BasicIntQueue implements IntQueue {
private buf = []
def get() { buf.pop() }
def put(x) { buf << x }
}
You could then construct an object with the desired traits like so:
def q = new Filtering(self: new Incrementing(self: new BasicIntQueue()))
Related
Question
How can I overwrite a method in Groovy if the class implements an interface? If the class does not implement an interface I can overwrite the method, but if the class implements an interface the method does not overwrite.
Example without implement
interface IA {
void abc()
}
class A {
void abc() {
println "original"
}
}
x= new A()
x.abc()
x.metaClass.abc = {-> println "new" }
x.abc()
The output of this is
original
new
Example with implement
Consider the following example where class A implements interface IA
interface IA {
void abc()
}
class A implements IA {
void abc() {
println "original"
}
}
x= new A()
x.abc()
x.metaClass.abc = {-> println "new" }
x.abc()
The output in this case is
original
original
As mentioned in the comments, looks like this is a pretty embarrassing bug, unfortunately.
But depending on your actual scenario, it may be possible to work around the problem.
Use Groovy #Category
If you can control where the method will be called, then you can use a Groovy Category to replace the method within a block:
x= new A()
x.abc()
#Category(A)
class ReplaceAbc {
void abc() {
println 'new'
}
}
use(ReplaceAbc) {
x.abc()
}
Replace the instance with an anonymous sub-type of the original type
If you can re-assign the variable, then this is an obvious way to override the method:
x= new A()
x.abc()
x = new A() {
#Override
void abc() {
println 'new'
}
}
x.abc()
How can I overwrite a method in Groovy if the class implements an
interface?
There are a few ways to do it. One is with runtime extension methods.
See the project at github.com/jeffbrown/victorchoymetaprogramminginterface.
lib/src/main/groovy/victorchoymetaprogramminginterface/IA.groovy
package victorchoymetaprogramminginterface
interface IA {
String abc()
}
lib/src/main/groovy/victorchoymetaprogramminginterface/A.groovy
package victorchoymetaprogramminginterface
class A implements IA{
#Override
String abc() {
'A.abc'
}
}
lib/src/main/groovy/victorchoymetaprogramminginterface/extensions/SomeInterfaceExtensionMethods.groovy
package victorchoymetaprogramminginterface.extensions
import victorchoymetaprogramminginterface.IA
class SomeInterfaceExtensionMethods {
static String abc(IA ia) {
'SomeInterfaceExtensionMethods.abc'
}
}
lib/src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
moduleVersion=1.0
moduleName=Demo Extensions
staticExtensionClasses=victorchoymetaprogramminginterface.extensions.SomeInterfaceExtensionMethods
The following test passes:
lib/src/test/groovy/victorchoymetaprogramminginterface/TestInterfaceExtensions.groovy
package victorchoymetaprogramminginterface
import spock.lang.Specification
class TestInterfaceExtensions extends Specification {
def "test interface extensions"() {
setup:
def obj = new A()
expect:
obj.abc() == 'SomeInterfaceExtensionMethods.abc'
}
}
I have a class something like this
class SomeClass () {
Closure instClos
SomeClass (Closure clos) { instClos = clos} //constructor
def call() {instClos()}
}
what i'd like to be able to do is do implicit Class constructor like this
SomeClass myInst = {println "hello there}
myInst()
but that doesn't work and throws cast exception. you can make this work by writing [] round the closure to call the constructor. but its not pretty
SomeClass myInst = [{println "hello there}] // or myInst = new ({println "hello there}
myInst()
is there a nice way to create the object through assignment and have that closure stored automatically on the created class instance?
feel i'm missing some groovy syntax here that would sort this (PS i'd prefer not having to extend Closure if i can avoid that )
based on the input provided so far i provided an extended script to show the various options. I tried to add an asType closure to Closure and try and call {...} as SomeClass - but if i tried that the asType is never called so groovy must be using another mechanism when you try a coercion
class SomeClass {
Closure instClos
SomeClass (Closure clos) {
println "\tSomeClass constructor: Will constructor called"
instClos = clos
}
def call() {
println "\tSomeClass.call: calling closure "
return (instClos() + "!")
}
SomeClass asType (Closure clos) {
new SomeClass (instClos: clos)
}
}
//this will call the map constructor - needs to be explicitly provided
SomeClass me = [{println "map style construction"; "echo"}]
assert me() == "echo!"
//use new to get class instance with constructor
me = new SomeClass ({println "new SomeClass () construction"; "echo"})
assert me() == "echo!"
//using layered closure approach - doesnt read well though
def someClos = {new SomeClass(it)}
def c = someClos {println "trying layered closure ";"echo"}
assert c() == "echo!"
//extending the Closure class to add a method
ExpandoMetaClass.enableGlobally()
Closure.metaClass.some = {
if (it == SomeClass) {
new SomeClass (delegate)
}
}
//this will call .some() on closure
me = {println "hello will using .some() "; "echo"}.some ( SomeClass)
assert me() == "echo!"
I'm not aware of anyway to auto-coerce a closure. Even though groovy has closure coercion, it works by changing the closure's type, but it's still a closure, and is not layered. Some ideas:
1. Constructor
class SomeClass {
Closure instClos
SomeClass (Closure clos) { instClos = clos} //constructor
def call() {instClos() + "!"}
}
def c = new SomeClass( { "echo" } )
assert c() == "echo!"
2. Map constructor
class SomeClass {
Closure instClos
def call() {instClos() + "!"}
}
SomeClass c = [instClos: { "echo" }]
assert c() == "echo!"
3. Closure metaprogramming
(Needs enableGlobally())
ExpandoMetaClass.enableGlobally()
Closure.metaClass.some = { new SomeClass(delegate) }
def c = { "echo" }.some()
assert c() == "echo!"
4. Another closure layering
class SomeClass {
Closure instClos
SomeClass (Closure clos) { instClos = clos} //constructor
def call() {instClos() + "!"}
}
def some = { new SomeClass(it) }
def c = some { "echo" }
assert c() == "echo!"
5. Override Closure's asType
ExpandoMetaClass.enableGlobally()
def asType = Closure.metaClass.asType
Closure.metaClass.asType = { Class c ->
(c == SomeClass) ? new SomeClass(delegate) : asType(c)
}
def c = { "echo" } as SomeClass
assert c() == "echo!"
If you have enough flexibility in your design you TRULY only need one method, SomeClass.call(), then you could specify it as an interface instead:
interface SomeClass {
def call()
}
Groovy long ago anticipated the case that Java 8 formalizes with the #FunctionalInterface annotation. If you assign a Groovy Closure to variable or formal parameter of interface type, where the interface has only one method (like SomeClass as defined above), the Groovy compiler will coerce the closure into an instance of that interface. So, given the interface declaration above, the following code:
SomeClass myInst = { println "hello there" }
myInst()
prints "hello there".
I'm seeing a rather strange thing with the new Groovy trait implementation. I have a (single method interface) class that implements a call() method so I can call call its only method just like a closure: instance() instead of having to do instance.call() . However as soon as I introduce such a reference (a Callable) using a trait that breaks. Anyone who can give a hint if this is something that is as expected or is there a workaround to that?
class MethodCallSpec extends Specification {
def "call a callable"() {
expect:
def thing = new Callable()
"hello" == thing.call("hello")
}
def "call a callable like a closure"() {
expect:
def thing = new Callable()
"hello" == thing("hello")
}
def "call with callable"() {
expect:
def thing = new SomethingWithCallable()
"hello" == thing.doSomething("hello")
}
}
class Callable {
Object call(def message) {
message
}
}
trait WithCallable {
Callable callable = new Callable();
}
class SomethingWithCallable implements WithCallable {
def doSomething(def message) {
callable(message) // this breaks unless written as callable.call(message)
}
}
I have two Spock specifications, both test a long procedure from a different starting point, so it's like
#Stepwise
class FooSpec extends Specification {
def "setup1"() {...}
def "setup2"() {...}
def "common1"() {...}
def "common2"() {...}
...
}
#Stepwise
class BarSpec extends Specification {
def "setup3"() {...}
def "setup4"() {...}
def "common1"() {...}
def "common2"() {...}
...
}
Now I'd like to refactor my code to deduplicate all the common* feature methods, that are to be executed after the different setups.
I tried to use subclassing, but the superclass' feature methods are executed before and not after the subclass' ones. I also tried to write an own Spock extension (Spock version 0.7 for Groovy 2), but couldn't find a way to implement my desired behaviour there.
Consulting the source code of StepwiseExtension, I finally managed to come up with my own solution:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
#ExtensionAnnotation(BeforeSuperExtension)
#interface BeforeSuper {}
This annotation marks feature methods in a #Stepwise test, that should be executed before super's feature methods.
The extension implementation will rearrange the execution order accordingly:
class BeforeSuperExtension extends AbstractAnnotationDrivenExtension<BeforeSuper>
{
def beforeSuper = []
#Override
void visitFeatureAnnotation(BeforeSuper annotation, FeatureInfo feature)
{
beforeSuper << feature
}
#Override
void visitSpec(SpecInfo spec)
{
def superFeatures = spec.superSpec.allFeaturesInExecutionOrder
def afterSuper = spec.features - beforeSuper
(beforeSuper + superFeatures + afterSuper).eachWithIndex { f, i ->
f.executionOrder = i
}
}
}
Put the common* methods in a base class, and add two subclasses with a setupSpec() method (instead of the setup* methods).
I've implemented the opposite strategy, with an annotation #AfterSubSpec that tells common methods in the superclass to run after methods in the subclass:
class AfterSubSpecExtension extends AbstractAnnotationDrivenExtension<AfterSubSpec> {
def afterSub = []
#Override
void visitFeatureAnnotation(AfterSubSpec annotation, FeatureInfo feature) {
afterSub << feature
}
#Override
void visitSpec(SpecInfo spec) {
def subSpecFeatures = spec.bottomSpec.allFeaturesInExecutionOrder - afterSub
(subSpecFeatures + afterSub).eachWithIndex { f, i -> f.executionOrder = i }
}
}
I have a mixin class that bundles functionality for different types that do not share a common heritage. The mixing is applied using the #Mixin annotation, so it is handled at compile time.
Some of the mixin methods return this as the result of a method call. The problem is that the this is of the mixing type and not the type of the base class. When I want to work typed in the rest of the application a ClassCastException is thrown saying that the mixing type can not be cast to the base type.
In the example code below return this returns an object of type AMixin instead of an Object of type BaseClass.
How can I have return this return an object of type BaseClass instead of an object of type AMixin?
class AMixin {
def getWhatIWant(){
if(isWhatIwant){
return this
} else {
getChildWhatIWant()
}
}
def getChildWhatIWant(){
for (def child in childred) {
def whatIWant = child.getWhatIWant()
if (whatIWant) {
return whatIWant
}
}
return null
}
}
#Mixin(AMixin)
class BaseClass {
boolean isWhatiWant
List<baseClass> children
}
I just ran into this same situation. I solved it by setting 'this' from the concrete class into a private variable 'me' inside the concrete class and return 'me' in the Mixin classes. For example:
class MyMixin {
def mixinMethod() {
// do stuff
return me
}
}
#Mixin(MyMixin)
class MyConcreteClass {
private MyConcreteClass me
MyConcreteClass() {
me = this
}
}
I feel like it's a bit kludgy, but I think it's a lot simpler than this other solution. I personally need the ability to use the same Mixin in multiple classes, and it sounds like this other proposed solution would not allow for that if you cannot assign multiple Categories to a single Mixin class.
I created the class Base added the category to the AMixin Class and the BaseClass extends from Base.....(http://groovy.codehaus.org/Category+and+Mixin+transformations)
Executed this in GroovyConsole I get
BaseClass#39c931fb
class Base {
boolean isWhatIwant
List<BaseClass> children
}
#Category(Base)
class AMixin {
def getWhatIWant(){
if(isWhatIwant){
return this
} else {
getChildWhatIWant()
}
}
def getChildWhatIWant(){
for (def child in children) {
def whatIWant = child.getWhatIWant()
if (whatIWant) {
return whatIWant
}
}
return null
}
}
#Mixin(AMixin)
public class BaseClass extends Base {
}
def b = new BaseClass(isWhatIwant:true)
println b.getWhatIWant()
EDIT just a DummyClass. I know it's very awkward that It works....I'm sure Guillaume Laforge could answer how this works...
class DummyClass {
}
#Category(DummyClass)
class AMixin {
def getWhatIWant(){
if(isWhatIwant){
return this
} else {
getChildWhatIWant()
}
}
def getChildWhatIWant(){
for (def child in children) {
def whatIWant = child.getWhatIWant()
if (whatIWant) {
return whatIWant
}
}
return null
}
}
#Mixin(AMixin)
public class BaseClass extends DummyClass {
boolean isWhatIwant
List<BaseClass> children
}
def b = new BaseClass(isWhatIwant:true)
println b.getWhatIWant()