How to create extension method like C# - groovy

I want to attach public method to the class.
This is called extension method in C#.
package extensionMethods
class A {
def testA() {}
//def testB() {} Need to add a public method to this class A but we don't have access to the class
}
class B {
def test() {
def a = new A();
a.testA()
a.testB() //Need to add a public method to the Class A without defining the method in the class A
}
}
//In C# way -> Extension method
class C {
/* void testB(this A a) {
}*/
}
How can we achieve the similar approach in Groovy?
In the above example I want to attach method testB() to class A

You will want something like this:
package something
class SomeExtensionClass {
static void testB(A self) {
// ...
}
}
Then your META-INF/services/org.codehaus.groovy.runtime.ExtensionModule extension descriptor...
moduleName=Test module for specifications
moduleVersion=1.0-test
extensionClasses=something.SomeExtensionClass
See http://groovy-lang.org/metaprogramming.html#_extension_modules for more info.

Related

How can we replace a interface method in groovy?

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'
}
}

Mono.Cecil add an internal class

I want to add an inner class using Mono.Cecil
public class MyClass
{
private class InternalClass
{
}
}
How can I do that?
The solution is
internalType = new TypeDefinition(
"", "InternalClass",
TypeAttributes.NestedPrivate,
module.Import(typeof(object)));
type.NestedTypes.Add(internalType);

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

How can I get the name of a class from a static method on that class, in haxe?

Normally I would just use Type.getClassName(Type.getClass(this), but obviously that doesn't work because there is no this. Any ideas?
If that is a static method, since there is no static member inheritance in Haxe, you already know what class it belongs to. So I would recommend hard-coding the class.
Or, you can use... macros!
import haxe.macro.Context;
import haxe.macro.Expr;
class ClassNameHelper {
macro static public function getClassName():ExprOf<String> {
return { expr: EConst(CString(Context.getLocalClass().toString())), pos: Context.currentPos() }
}
}
class Test {
public static function main() {
trace(ClassNameHelper.getClassName()); //Test
}
}

Use Groovy Category implicitly in all instance methods of class

I have simple Groovy category class which adds method to String instances:
final class SampleCategory {
static String withBraces(String self) {
"($self)"
}
}
I want to use this category in my unit tests (for example). It looks like this:
class MyTest {
#Test
void shouldDoThis() {
use (SampleCategory) {
assert 'this'.withBraces() == '(this)'
}
}
#Test
void shouldDoThat() {
use (SampleCategory) {
assert 'that'.withBraces() == '(that)'
}
}
}
What I'd like to achieve, however, is ability to specify that category SampleCategory is used in scope of each and every instance method of MyTest so I don't have to specify use(SampleCategory) { ... } in every method.
Is it possible?
You can use mixin to apply the category directly to String's metaClass. Assign null to the metaClass to reset it to groovy defaults. For example:
#Before void setUp() {
String.mixin(SampleCategory)
}
#After void tearDown() {
String.metaClass = null
}
#Test
void shouldDoThat() {
assert 'that'.withBraces() == '(that)'
}
Now you have the option to use extension modules instead of categories:
http://mrhaki.blogspot.se/2013/01/groovy-goodness-adding-extra-methods.html
On the plus side Intellij will recognize the extensions. I've just noticed that it doesn't even need to be a separate module as suggested by the link, just add META-INF/services/org.codehaus.groovy.runtime.ExtensionModule to the project:
# File: src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
moduleName = module
moduleVersion = 1.0
extensionClasses = SampleExtension
The extension class is pretty much defined like a normal category:
class SampleExtension {
static String withBraces(String self) {
"($self)"
}
}
Can be used like:
def "Sample extension"() {
expect: 'this'.withBraces() == '(this)'
}
If you are using Spock there is a #Use annotation that can be used on the specifications. The drawback with that is that Intellij will not recognize it.

Resources