Type of 'return this' in a Groovy #Mixin - groovy

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()

Related

How to access super or parent method from groovy anonymous class?

I want to know how we can access a parent method from an overriding child method using an anonymous class. Shown in the example below cc was declared as an anonymous class. How do I override the parent method testMethod1, yet still have access to the original ones? The keyword super doesn't seem to help in my case.
abstract class ParentClass {
def prop1="abc"
def testMethod1 () {
println("testMethod1 in parent");
}
def testMethod2 () {
println("testMethod2 in parent");
}
}
class ChildClass extends ParentClass {
}
def cc = [
testMethod1:{
super.testMethod1(); // Error, why? What is the proper way to call parent method?
println("testMethod1 in child");
},
testMethod2:{
println("testMethod2 in child");
}
] as ChildClass;
println("Starting");
println (cc.prop1);
cc.testMethod2();
//cc.testMethod1();
The result is:
Starting
abc
testMethod2 in child
You can try it here:
https://groovyconsole.appspot.com/script/5076402630033408
Groovy closure does not support super to access members of super class.
See: https://groovy-lang.org/closures.html
The following code is recommended:
abstract class ParentClass {
def prop1="abc"
def testMethod1() {
println("testMethod1 in parent")
}
def testMethod2() {
println("testMethod2 in parent")
}
}
class ChildClass extends ParentClass {
def testMethod1() {
super.testMethod1()
println("testMethod1 in child")
}
def testMethod2() {
println("testMethod2 in child")
}
}
cc = new ChildClass()
println("Starting")
println(cc.prop1)
cc.testMethod1()
cc.testMethod2()
The output is:
Starting
abc
testMethod1 in parent
testMethod1 in child
testMethod2 in child
Here is the AIC way:
cc = new ParentClass() {
def testMethod1() {
super.testMethod1()
println("testMethod1 in child")
}
def testMethod2() {
println("testMethod2 in child")
}
}

How do I add properties to a closure?

When I try to add a property to a custom Closure class...
class MyClosure extends Closure<Object> {
def myProperty
MyClosure() {
super(null)
}
Object doCall(final Closure inner) {
// do something...
}
}
println new MyClosure().myProperty
I get an error:
java.lang.NullPointerException: Cannot get property 'myProperty' on null object
It seems that this is related to the Closure class that has some behaviour I don't really understand, as when I remove the implements part there's no problem:
class MyClosure {
def myProperty
}
println new MyClosure().myProperty
So what do I need to do when I want to add a property to a custom closure?
You need to change closure resolve strategy:
class MyClosure extends Closure<Object> {
def myProperty = "value"
MyClosure() {
super(null)
}
Object doCall(final Closure inner) {
// do something...
}
}
def closure = new MyClosure()
closure.resolveStrategy = Closure.TO_SELF
println closure.myProperty // value

groovy define metaclass with its own custom methods and set it for the object

Is it possible to set metaclass for the object in groovy with its custom methods? I mean something like some kind of dynamic inheritance...
For example something like this
class Original {
def my_method() { }
}
class Meta {
def meta_method() { }
}
def obj = new Original()
obj.metaClass = new Meta()
obj.meta_method()
You can use traits to achieve this kind of things. It's a little more "high level" than directly manipuling the metaclass
​class Original {
def my_method() { }
}
trait Meta {
def meta_method() { }
}
def obj = new Original()​.withTraits Meta
​obj.meta_method()​
see: http://docs.groovy-lang.org/next/html/documentation/core-traits.html#_implementing_a_trait_at_runtime

How to check whether a Groovy class overrides a parent's method

I have two Groovy classes, Child1 and Child2, which derive from an abstract parent class Parent. The parent class implements three methods, only different in their parameters (i.e. their method names are the same).
Now I have an instance of the child class. The task is to check whether that object's class implements (overrides) one or more of the parent's methods.
I tried with Groovy's Inspector on the child class object. This gives me a list of all methods, but I am not sure how to read the output. In particular I do not understand whether the method I am looking for is implement in the child class, or only in the parent class.
Can anybody help me with this, do I maybe need another way of introspection?
Hope this helps. I still feel there is a groovier way. Try using collectInheritedMethods() to see if you get what you wanted. I deliberately wanted to return a list of matched methods instead of just a flag because you can also see the methods that are implemented from super class, Groovy truth (if(collectInheritedMethods(..))) on the list will be sufficient for flagging.
abstract class Parent {
void method1() { println "No Param" }
void method1( def a ) { println "param: $a" }
void method1( List a, Map b ) { println "param: $a and $b" }
}
class Child extends Parent {
void method1() { println "A: no param" }
void method1( def a ) { println "A: param $a" }
void method1( def a, def b ) { println "A: param $a and $b" }
}
List collectInheritedMethods( Class parent, Class child ) {
List inheritedMethods = []
def parentMethods = parent.declaredMethods.findAll { !it.synthetic }
def childMethods = child.declaredMethods.findAll { !it.synthetic }
for( chMet in childMethods ) {
for( paMet in parentMethods ) {
if( chMet.name == paMet.name &&
chMet.parameterTypes == paMet.parameterTypes &&
chMet.returnType == paMet.returnType ) {
inheritedMethods << child.getMethod( chMet.name,
chMet.parameterTypes )
.toGenericString()
//if only a flag is required to check if method implemented
//flag = true
//break
}
}
}
//Groovier way
/*inheritedMethods = childMethods.findAll { chMet ->
parentMethods.findAll { paMet ->
chMet.name == paMet.name &&
chMet.parameterTypes == paMet.parameterTypes &&
chMet.returnType == paMet.returnType
}
}*/
inheritedMethods
}
assert collectInheritedMethods( Parent, Child ) ==
["public void Child.method1()",
"public void Child.method1(java.lang.Object)"]
So I ended up with this solution, which does exactly what I wanted:
def pattern = ~/^public void ... $/
for(method in obj.metaClass.methods.findAll { it ==~ pattern })
{
/* Do some stuff... */
}

Method aliasing in class with Groovy

I'm going to internationalize groovy API abit.
For final class (e.g. String)
String.metaClass.вСтроку = {-> this.toString() }
However, this will create additional closure. Isn't there any way to just alias method with another method?
Something like this:
String.metaClass.вСтроку = String.metaClass.&toString
You could use #Category transform like this
#Category(String) class StringInternationalization {
String вСтроку() {
this.toString()
}
int длина() {
this.length()
}
}
class ApplyMixin {
static {
String.mixin(StringInternationalization)
final helloString = "Привет мир!"
println helloString.вСтроку()
assert helloString.длина() == helloString.length()
}
}
new Main()
This will create 1 Category class for each localised class and one class to apply all mixin transformations(to register all methods.) Also should be faster, then individual closures.
More reading here: http://groovy.codehaus.org/Category+and+Mixin+transformations

Resources