{"id":13102,"date":"2017-08-24T16:49:00","date_gmt":"2017-08-24T14:49:00","guid":{"rendered":"https:\/\/touk.pl\/blog\/?guid=3b2d99dbb834271d0b2135c9986bb3b1"},"modified":"2022-07-29T11:20:31","modified_gmt":"2022-07-29T09:20:31","slug":"using-kotlin-extensions-in-groovy","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2017\/08\/24\/using-kotlin-extensions-in-groovy\/","title":{"rendered":"Using Kotlin extensions in Groovy"},"content":{"rendered":"<h1 id=\"using-kotlin-extensions-in-groovy\">Using Kotlin extensions in Groovy<\/h1>\n<h2 id=\"extensions-in-kotlin-and-groovy\">Extensions in Kotlin and Groovy<\/h2>\n<p><a href=\"https:\/\/kotlinlang.org\/\">Kotlin<\/a> and <a href=\"http:\/\/groovy-lang.org\/\">Groovy<\/a> have mechanisms for extending existing classes without using inheritance or decorators. In both languages, the mechanisms are called extension methods. Their source code looks different, but generated bytecode is quite similar. Thanks to that, Groovy is able to use Kotlin extensions just like its own.<\/p>\n<p>Why would I want to use such extensions in Groovy? The main reason is that I want to test my extensions using the best testing framework available for the JVM &#8211; <a href=\"http:\/\/spockframework.org\/\">Spock Framework<\/a>.<\/p>\n<p>Code is available <a href=\"https:\/\/github.com\/alien11689\/kotlin-extensions-in-groovy\">here<\/a>.<\/p>\n<h2 id=\"extensions-in-kotlin\">Extensions in Kotlin<\/h2>\n<p>There are many types of <a href=\"https:\/\/kotlinlang.org\/docs\/reference\/extensions.html\">extensions in Kotlin<\/a>. I decided to focus only on extension functions and properties.<\/p>\n<p>As an example, I extend the <code>java.lang.String<\/code> class. First, I create an extension function <code>skipFirst<\/code>, which skips first <code>N<\/code> characters:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\">fun String.skipFirst(n: Int) = if (length &gt; n) this.substring(n) else \"\"\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Next, I create an extension property <code>answer<\/code>, which is the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy#Answer_to_the_Ultimate_Question_of_Life.2C_the_Universe.2C_and_Everything_.2842.29\">Answer to the Ultimate Question of Life, the Universe, and Everything<\/a>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\">val String.answer\r\n    get() = 42\r\n<\/pre>\n<p>Both extensions are declared in package <code>com.github.alien11689.extensions<\/code>, in file called <code>StringExtensions<\/code>. However, the generated class in target directory is named <code>StringExtensionsKt<\/code> and this is the name that must be used when accessing from other languages. Specific class name can be forced by annotation <a href=\"https:\/\/kotlinlang.org\/api\/latest\/jvm\/stdlib\/kotlin.jvm\/-jvm-name\/\"><code>@file:JvmName<\/code><\/a>.<\/p>\n<h2 id=\"using-kotlin-extensions-in-groovy-1\"><span id=\"using-kotlin-extensions-in-groovy-2\">Using Kotlin extensions in Groovy<\/span><\/h2>\n<p>There are two ways for using extensions in Groovy that are supported by good IDEs. First, you can declare scope where the extensions are available by <code>use<\/code> method:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\">def \"should use extension method\"() {\r\n    expect:\r\n        use(StringExtensionsKt) {\r\n            input.skipFirst(n) == expected\r\n        }\r\n    where:\r\n        input  | n | expected\r\n        \"abcd\" | 3 | \"d\"\r\n        \"abcd\" | 6 | \"\"\r\n        \"\"     | 3 | \"\"\r\n}\r\n\r\ndef \"should use extension property\"() {\r\n    expect:\r\n        use(StringExtensionsKt) {\r\n            \"abcd\".answer == 42\r\n        }\r\n}\r\n<\/pre>\n<p>It is acceptable, but is not very convenient. The second and much better way is to use an extension module definition. The extension module is defined in file <code>org.codehaus.groovy.runtime.ExtensionModule<\/code> in directory <code>src\/main\/resources\/META-INF\/services\/<\/code>. The same directory is monitored by <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/util\/ServiceLoader.html\">ServiceLoader<\/a>, but the file format is completely different:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\">moduleName=string-extension-module\r\nmoduleVersion=1.0.0\r\nextensionClasses=com.github.alien11689.extensions.StringExtensionsKt\r\n<\/pre>\n<p>The tests look much better now:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\">def \"should use extension method\"() {\r\n    expect:\r\n        input.skipFirst(n) == expected\r\n    where:\r\n        input  | n | expected\r\n        \"abcd\" | 3 | \"d\"\r\n        \"abcd\" | 6 | \"\"\r\n        \"\"     | 3 | \"\"\r\n}\r\n\r\ndef \"should use extension property\"() {\r\n    expect:\r\n        \"abcd\".answer == 42\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"Extensions in Kotlin and GroovyKotlin and Groovy have mechanisms for extending existing classes without using inheritance or decorators. In both languages, the mechanisms are called extension methods. Their source code looks different, but generated by&#8230;\n","protected":false},"author":54,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[613,50,612,556],"class_list":{"0":"post-13102","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-extensions","8":"tag-groovy","9":"tag-jvm","10":"tag-kotlin"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13102","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/users\/54"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=13102"}],"version-history":[{"count":11,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13102\/revisions"}],"predecessor-version":[{"id":14707,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/13102\/revisions\/14707"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=13102"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=13102"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=13102"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}