{"id":12723,"date":"2015-11-14T16:24:00","date_gmt":"2015-11-14T15:24:00","guid":{"rendered":"https:\/\/touk.pl\/blog\/?guid=958dc4e03e732e9d451b558c1faf5fac"},"modified":"2022-08-03T12:48:48","modified_gmt":"2022-08-03T10:48:48","slug":"kotlins-extensions-for-each-class","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2015\/11\/14\/kotlins-extensions-for-each-class\/","title":{"rendered":"Kotlin&#8217;s extensions for each class"},"content":{"rendered":"<p>Extensions in Kotlin are very powerful mechanism. It allows for add any method to any of existing classes. Each instance has (as in Java) <code>equals<\/code>, <code>toString<\/code> and <code>hashCode<\/code> methods, but there is much more in Kotlin.<\/p>\n<h2 id=\"example-classes\">Example classes<\/h2>\n<p>Let&#8217;s define some simple classes describing person: normal class and data class.<\/p>\n<pre class=\"brush: java\">class PersonJaxb {\r\n    var firstName: String? = null\r\n    var lastName: String? = null\r\n    var age: Int? = null\r\n}<\/pre>\n<p>data class Person(val firstName: String, val lastName: String, val age: Int)<\/p>\n<p>&nbsp;<\/p>\n<h2 id=\"normal-class-extensions\">Normal class extensions<\/h2>\n<p>All instances have methods described below.<\/p>\n<h3 id=\"apply-method\"><code>apply<\/code> method<\/h3>\n<p>I often work with jaxb classes similar to <code>PersonJaxb<\/code>, which has not all arg constructor and all fields must be set via setters. Kotlin helps to deal with it via <code>apply<\/code> method. Target instance is provided as delagate to closure so we could define all fields values in it and returns <code>this<\/code>. The signature is <code>T.apply(f: T.() -&gt; Unit): T<\/code>.<\/p>\n<pre class=\"brush: java\">@Test\r\nfun applyTest() {\r\n    \/\/when\r\n    val person = PersonJaxb().apply {\r\n        firstName = \"John\"\r\n        lastName = \"Smith\"\r\n        age = 20\r\n    }<\/pre>\n<p>\/\/then<br \/>\nassertEquals(20, person.age)<br \/>\nassertEquals(&#8220;John&#8221;, person.firstName)<br \/>\nassertEquals(&#8220;Smith&#8221;, person.lastName)<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<h3 id=\"let-method\"><code>let<\/code> method<\/h3>\n<p>Another extension is <code>let<\/code> method which is similar to map operation for collections. It has signature <code>T.let(f: (T) -&gt; R): R<\/code>. <code>this<\/code> is passed as parameter to given closure\/function.<\/p>\n<pre class=\"brush: java\">@Test\r\nfun letTest() {\r\n    \/\/when\r\n    val fullName = Person(\"John\", \"Smith\", 20).let {\r\n        \"${it.firstName} ${it.lastName}\"\r\n    }<\/pre>\n<p>\/\/then<br \/>\nassertEquals(&#8220;John Smith&#8221;, fullName)<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<h3 id=\"run-method\"><code>run<\/code> method<\/h3>\n<p><code>run<\/code> method looks like merge of <code>apply<\/code> and <code>let<\/code> methods: access to <code>this<\/code> is via delegate as in <code>apply<\/code>, but it also returns value as in <code>let<\/code> method. It has signature <code>T.run(f: T.() -&gt; R): R<\/code>.<\/p>\n<pre class=\"brush: java\">@Test\r\nfun runTest() {\r\n    \/\/when\r\n    val fullName = Person(\"John\", \"Smith\", 20).run {\r\n        \"$firstName $lastName\"\r\n    }<\/pre>\n<p>\/\/then<br \/>\nassertEquals(&#8220;John Smith&#8221;, fullName)<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<h3 id=\"to-method\"><code>to<\/code> method<\/h3>\n<p>Each instance has also defined <code>to<\/code> infix operator, which is used to create <code>Pair<\/code>. Pairs is helpful to create map entries. It has signature <code>A.to(that: B): Pair&lt;A, B&gt;<\/code>.<\/p>\n<pre class=\"brush: java\">@Test\r\nfun toTest() {\r\n    \/\/when\r\n    val pair = Person(\"John\", \"Smith\", 20) to 5<\/pre>\n<p>\/\/then<br \/>\nassertEquals(Person(&#8220;John&#8221;, &#8220;Smith&#8221;, 20), pair.first)<br \/>\nassertEquals(5, pair.second)<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<h2 id=\"data-class-methods\">Data class methods<\/h2>\n<p>Data class instances have also some other helpful methods (which are not extensions, but are generated for us).<\/p>\n<h3 id=\"componentx-methods\"><code>componentX<\/code> methods<\/h3>\n<p>Data class <code>Person<\/code> has three fields and it has component method generated for each of them: <code>component1<\/code> for <code>firstName<\/code>, <code>component2<\/code> for <code>lastName<\/code> and <code>component3<\/code> for <code>age<\/code>.<\/p>\n<pre class=\"brush: java\">@Test\r\nfun componentsTest() {\r\n    \/\/when\r\n    val p = Person(\"John\", \"Smith\", 20)<\/pre>\n<p>\/\/then<br \/>\nassertEquals(&#8220;John&#8221;, p.component1())<br \/>\nassertEquals(&#8220;Smith&#8221;, p.component2())<br \/>\nassertEquals(20, p.component3())<br \/>\n}<\/p>\n<p>Why is it helpful? <code>componentX<\/code> methods are used in extracting (similar to Scala case classes extracting mechanism), e. g.:<\/p>\n<pre class=\"brush: java\">@Test\r\nfun extractingTest() {\r\n    \/\/when\r\n    val (first, last, age) = Person(\"John\", \"Smith\", 20)<\/pre>\n<p>\/\/then<br \/>\nassertEquals(20, age)<br \/>\nassertEquals(&#8220;John&#8221;, first)<br \/>\nassertEquals(&#8220;Smith&#8221;, last)<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<h3 id=\"copy-method\"><code>copy<\/code> method<\/h3>\n<p><code>copy<\/code> method allows to create new instance based on current instance.<\/p>\n<pre class=\"brush: java\">@Test\r\nfun copyTest() {\r\n    \/\/when\r\n    val person = Person(\"John\", \"Smith\", 20).copy(lastName = \"Kowalski\", firstName = \"Jan\")<\/pre>\n<p>\/\/then<br \/>\nassertEquals(Person(&#8220;Jan&#8221;, &#8220;Kowalski&#8221;, 20), person)<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<h2 id=\"summary\">Summary<\/h2>\n<p>Kotlin&#8217;s extensions for each instances are very simple and help to solve many problems. The code written with these extensions is much more readable and concise than written in Java.<\/p>\n<p>Sources are available <a href=\"https:\/\/github.com\/alien11689\/kotlins-extenstions-for-each-class\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"Extensions in Kotlin are very powerful mechanism. It allows for add any method to any of existing classes. Each instance has (as in Java) equals, toString and hashCode methods, but there is much more in Kotlin.Example classesLet&#8217;s define some simple cl&#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":[556],"class_list":{"0":"post-12723","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-kotlin"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/12723","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=12723"}],"version-history":[{"count":8,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/12723\/revisions"}],"predecessor-version":[{"id":14930,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/12723\/revisions\/14930"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=12723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=12723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=12723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}