├── .gitignore
├── .idea
├── kotlinc.xml
├── libraries
│ └── KotlinJavaRuntime.xml
├── misc.xml
├── modules.xml
├── uiDesigner.xml
├── vcs.xml
└── workspace.xml
├── IdiomaticKotlin.iml
├── README.md
└── src
├── chap01_extension_functions
├── ExtensionFunction.kt
├── ExtensionProperties.kt
└── InheritanceAndPolymorphism.kt
├── chap02_sealed_classes
├── LegacyApproach.kt
└── SealedClass.kt
├── chap03_infix_function
└── InfixFunction.kt
├── chap04_class_delegation
└── DelegationSample.kt
├── chap05_local_function
└── LocalFunction.kt
├── chap06_object_and_singleton
└── Singleton.kt
├── chap07_sequence
└── SequenceSample.kt
├── chap08_lambdas_sam_constructors
├── Invoke.kt
├── LambdaPass.kt
├── SAMConversion.kt
└── View.java
├── chap09_lambda_receiver_dsl
└── ViewCreator.kt
├── chap10_elvis_operator
├── ElvisSyntax.kt
├── ExpandedElvis.kt
└── SafeCall.kt
├── chap11_property_delegation
├── Delegate.kt
├── LazyTest.kt
├── ManualLazy.kt
└── ObservableTest.kt
├── chap12_higher_order_function_and_function_type
└── FunctionType.kt
├── chap13_inline
├── InlinedFilter.kt
├── InlinedFunctionReference.kt
├── LambdaInstance.kt
└── NotInlinedFilter.kt
├── chap14_lambda_and_control_flows
├── AnonymousFunctionReturns.kt
├── InlineReturn.kt
├── LambdaReturn.kt
├── NotinlineLambdaReturn.kt
└── ReturnWithLabels.kt
├── chap15_reified_parameters
├── ReifiedParameter.kt
├── TypeErasure.kt
└── TypeErasureLimitation.kt
├── chap16_noinline_crossinline
├── Crossinline.kt
├── Noinline.kt
└── Safidfngd.java
└── chap17_variance
├── Contravariance.java
├── Covariance.java
├── DeclarationSiteContravariance.kt
├── DeclarationSiteCovariance.kt
├── GenericInvariance.java
├── UseSiteVariance.kt
└── Variance.java
/.gitignore:
--------------------------------------------------------------------------------
1 | out/
2 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/libraries/KotlinJavaRuntime.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 | 1532314320231
364 |
365 |
366 | 1532314320231
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 | file://$PROJECT_DIR$/src/chap17_variance/Variance.java
412 | 4
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
--------------------------------------------------------------------------------
/IdiomaticKotlin.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Idiomatic Kotlin
2 | Contains all the code presented in the Idiomatic Kotlin tutorial series.
3 |
4 | ## Chapters:
5 | 1. [Idiomatic Kotlin: Extension functions](https://medium.com/tompee/idiomatic-kotlin-extension-functions-67735491851f)
6 | 2. [Idiomatic Kotlin: Sealed Classes](https://medium.com/tompee/idiomatic-kotlin-sealed-classes-bf1772d9d607)
7 | 3. [Idiomatic Kotlin: Infix functions](https://medium.com/tompee/idiomatic-kotlin-infix-functions-eea833f70c90)
8 | 4. [Idiomatic Kotlin: Class Delegates](https://medium.com/tompee/idiomatic-kotlin-class-delegates-288b24c37ac8)
9 | 5. [Idiomatic Kotlin: Local functions](https://medium.com/tompee/idiomatic-kotlin-local-functions-4421f86ac864)
10 | 6. [Idiomatic Kotlin: Object and Singleton](https://medium.com/tompee/idiomatic-kotlin-object-and-singleton-183c3cfdbd26)
11 | 7. [Idiomatic Kotlin: Sequences](https://medium.com/tompee/idiomatic-kotlin-sequences-80ebbeec1115)
12 | 8. [Idiomatic Kotlin: Lambdas and SAM constructors](https://medium.com/tompee/idiomatic-kotlin-lambdas-and-sam-constructors-fe2075965bfb)
13 | 9. [Idiomatic Kotlin: Lambdas with Receiver and DSL](https://medium.com/tompee/idiomatic-kotlin-lambdas-with-receiver-and-dsl-3cd3348e1235)
14 | 10. [Idiomatic Kotlin: Elvis Operator](https://medium.com/tompee/idiomatic-kotlin-elvis-operator-d6f5639a5130)
15 | 11. [Idiomatic Kotlin: Property Delegates and Lazy](https://medium.com/tompee/idiomatic-kotlin-property-delegates-and-lazy-11207213a788)
16 | 12. [Idiomatic Kotlin: Higher-order functions and Function Types](https://medium.com/tompee/idiomatic-kotlin-higher-order-functions-and-function-types-adb59172796)
17 | 13. [Idiomatic Kotlin: Inline functions](https://medium.com/tompee/idiomatic-kotlin-inline-functions-e39b2f90a291)
18 | 14. [Idiomatic Kotlin: Lambdas and Control Flows](https://medium.com/tompee/idiomatic-kotlin-lambdas-and-control-flows-70a7a58d7a20)
19 | 15. [Idiomatic Kotlin: Reified Parameters](https://medium.com/tompee/idiomatic-kotlin-reified-parameters-e89f665ab026)
20 | 16. [Idiomatic Kotlin: Noinline and Crossinline](https://medium.com/tompee/idiomatic-kotlin-noinline-and-crossinline-e51014408ff0)
21 | 17. [Idiomatic Kotlin: Variance](https://medium.com/tompee/idiomatic-kotlin-variance-82355d9a71df)
22 | 18. [Idiomatic Kotlin: Annotations and Reflection](https://medium.com/tompee/kotlin-annotations-and-reflection-caa0d73bf39b)
23 | 19. [Idiomatic Kotlin: Annotation Processor and Code Generation](https://medium.com/tompee/kotlin-annotation-processor-and-code-generation-58bd7d0d333b)
24 |
25 | Check out all the other articles on the publication as well [here](https://medium.com/tompee).
26 |
--------------------------------------------------------------------------------
/src/chap01_extension_functions/ExtensionFunction.kt:
--------------------------------------------------------------------------------
1 | package chap01_extension_functions
2 |
3 | class ExtensionFunction {
4 | fun String.second(): Char {
5 | if (isEmpty()) throw NoSuchElementException("Char sequence is empty.")
6 | if (length < 2) throw NoSuchElementException("Char sequence length is less than 2.")
7 | return this[1]
8 | }
9 | }
--------------------------------------------------------------------------------
/src/chap01_extension_functions/ExtensionProperties.kt:
--------------------------------------------------------------------------------
1 | package chap01_extension_functions
2 |
3 | class ExtensionProperties {
4 | val String.second: Char
5 | get() {
6 | if (isEmpty()) throw NoSuchElementException("Char sequence is empty.")
7 | if (length < 2) throw NoSuchElementException("Char sequence length is less than 2.")
8 | return this[1]
9 | }
10 | }
--------------------------------------------------------------------------------
/src/chap01_extension_functions/InheritanceAndPolymorphism.kt:
--------------------------------------------------------------------------------
1 | package chap01_extension_functions
2 |
3 | class InheritanceAndPolymorphism {
4 | open class Base {
5 | open fun getString() = "Base"
6 | }
7 |
8 | fun Base.newString() = "BaseNewString"
9 |
10 | class Derived : Base() {
11 | override fun getString() = "Derived"
12 | }
13 |
14 | fun Derived.newString() = "DerivedNewString"
15 | }
16 |
--------------------------------------------------------------------------------
/src/chap02_sealed_classes/LegacyApproach.kt:
--------------------------------------------------------------------------------
1 | package chap02_sealed_classes
2 |
3 | class LegacyApproach {
4 | interface Class
5 |
6 | class Knight : Class
7 |
8 | class Priest : Class
9 |
10 | fun getClassString(clazz: Class): String {
11 | return when (clazz) {
12 | is Knight -> "Knight"
13 | is Priest -> "Priest"
14 | else -> throw IllegalArgumentException("Unknown class")
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/chap02_sealed_classes/SealedClass.kt:
--------------------------------------------------------------------------------
1 | package chap02_sealed_classes
2 |
3 | sealed class Attribute
4 |
5 | class Intelligence : Attribute()
6 |
7 | class Agility : Attribute()
8 |
9 | class Strength : Attribute()
10 |
11 | fun getAttributeString(attribute: Attribute): String {
12 | return when (attribute) {
13 | is Intelligence -> "Intelligence"
14 | is Strength -> "Strength"
15 | is Agility -> "Agility"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/chap03_infix_function/InfixFunction.kt:
--------------------------------------------------------------------------------
1 | package chap03_infix_function
2 |
3 | class InfixFunction {
4 | class Warrior(var hp: Int, var ap: Int) {
5 | infix fun attack(anotherWarrior: Warrior) {
6 | anotherWarrior.hp -= ap
7 | }
8 | }
9 |
10 | fun attackTest() {
11 | val warrior1 = Warrior(100, 20)
12 | val warrior2 = Warrior(100, 15)
13 |
14 | warrior1 attack warrior2
15 | println("Warrior 2 HP : ${warrior2.hp}")
16 | }
17 | }
--------------------------------------------------------------------------------
/src/chap04_class_delegation/DelegationSample.kt:
--------------------------------------------------------------------------------
1 | package chap04_class_delegation
2 |
3 | class DelegationSample {
4 | interface AttackType {
5 | fun getAttackType(): String
6 | }
7 |
8 | class Ranged : AttackType {
9 | override fun getAttackType(): String = "Ranged"
10 | }
11 |
12 | interface HeroType {
13 | fun getAttributeType(): String
14 | }
15 |
16 | class Strength : HeroType {
17 | override fun getAttributeType(): String = "Strength"
18 | }
19 |
20 | class Huskar : AttackType by Ranged(), HeroType by Strength()
21 | }
--------------------------------------------------------------------------------
/src/chap05_local_function/LocalFunction.kt:
--------------------------------------------------------------------------------
1 | package chap05_local_function
2 |
3 | class LocalFunction {
4 | // Local function
5 | fun login(username: String, password: String): Boolean {
6 | var something = 1
7 | fun validateInput(input: String) {
8 | something++
9 | if (input.isEmpty()) {
10 | throw IllegalArgumentException("Must not be empty")
11 | }
12 | }
13 | validateInput(username)
14 | validateInput(password)
15 | return true
16 | }
17 |
18 | data class Credentials(val username: String, val password: String)
19 |
20 | // Local extension function
21 | fun Credentials.validate() {
22 | fun validateInput(input: String) {
23 | if (input.isEmpty()) {
24 | throw IllegalArgumentException("Must not be empty")
25 | }
26 | }
27 | validateInput(username)
28 | validateInput(password)
29 | }
30 |
31 | fun login(credentials: Credentials) {
32 | credentials.validate()
33 | }
34 | }
--------------------------------------------------------------------------------
/src/chap06_object_and_singleton/Singleton.kt:
--------------------------------------------------------------------------------
1 | package chap06_object_and_singleton
2 |
3 | import java.io.Serializable
4 |
5 | object Singleton : Serializable {
6 | val text: String = "Hello from singleton"
7 |
8 | init {
9 | /* Do initialization here */
10 | }
11 | }
--------------------------------------------------------------------------------
/src/chap07_sequence/SequenceSample.kt:
--------------------------------------------------------------------------------
1 | package chap07_sequence
2 |
3 | // Copy of some stdlib functions. Use the actual function in stdlib for the latest code
4 | class SequenceSample {
5 | public inline fun Iterable.filter(predicate: (T) -> Boolean): List {
6 | return filterTo(ArrayList(), predicate)
7 | }
8 |
9 | public inline fun > Iterable.filterTo(destination: C, predicate: (T) -> Boolean): C {
10 | for (element in this) if (predicate(element)) destination.add(element)
11 | return destination
12 | }
13 |
14 | public fun Sequence.filter(predicate: (T) -> Boolean): Sequence {
15 | return FilteringSequence(this, true, predicate)
16 | }
17 |
18 | internal class FilteringSequence(
19 | private val sequence: Sequence,
20 | private val sendWhen: Boolean = true,
21 | private val predicate: (T) -> Boolean
22 | ) : Sequence {
23 |
24 | override fun iterator(): Iterator = object : Iterator {
25 | val iterator = sequence.iterator()
26 | var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue
27 | var nextItem: T? = null
28 |
29 | private fun calcNext() {
30 | while (iterator.hasNext()) {
31 | val item = iterator.next()
32 | if (predicate(item) == sendWhen) {
33 | nextItem = item
34 | nextState = 1
35 | return
36 | }
37 | }
38 | nextState = 0
39 | }
40 |
41 | override fun next(): T {
42 | if (nextState == -1)
43 | calcNext()
44 | if (nextState == 0)
45 | throw NoSuchElementException()
46 | val result = nextItem
47 | nextItem = null
48 | nextState = -1
49 | @Suppress("UNCHECKED_CAST")
50 | return result as T
51 | }
52 |
53 | override fun hasNext(): Boolean {
54 | if (nextState == -1)
55 | calcNext()
56 | return nextState == 1
57 | }
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/src/chap08_lambdas_sam_constructors/Invoke.kt:
--------------------------------------------------------------------------------
1 | package chap08_lambdas_sam_constructors
2 |
3 | fun main(args: Array) {
4 | // Regular f(x)
5 | val addOffset = { x: Int -> x + 1 }
6 | println(addOffset(2))
7 |
8 | // Invoke
9 | println(addOffset.invoke(2))
10 |
11 | // Anonymous invocation
12 | println({ x: Int -> x + 1 }(2))
13 | }
14 |
--------------------------------------------------------------------------------
/src/chap08_lambdas_sam_constructors/LambdaPass.kt:
--------------------------------------------------------------------------------
1 | package chap08_lambdas_sam_constructors
2 |
3 | fun main(args: Array) {
4 | fun addOffset(base: Int, lambda: (Int) -> Int): Int {
5 | return lambda.invoke(base)
6 | }
7 |
8 | fun addOffset(lambda: (Int) -> Int, base: Int): Int {
9 | return lambda.invoke(2)
10 | }
11 |
12 | // Last argument lambda
13 | addOffset(2) { x: Int -> x + 1 }
14 |
15 | // General syntax
16 | addOffset({ x: Int -> x + 1 }, 2)
17 | }
--------------------------------------------------------------------------------
/src/chap08_lambdas_sam_constructors/SAMConversion.kt:
--------------------------------------------------------------------------------
1 | package chap08_lambdas_sam_constructors
2 |
3 | fun main(args: Array) {
4 | // Assigning to a variable
5 | val runnable: Runnable = Runnable { print("I am a runnable") }
6 |
7 | // Returning a specific type of functional interface
8 | fun createOnClickListener(): View.OnClickListener {
9 | return View.OnClickListener { v -> print("I am clicked") }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/chap08_lambdas_sam_constructors/View.java:
--------------------------------------------------------------------------------
1 | package chap08_lambdas_sam_constructors;
2 |
3 | public class View {
4 | interface OnClickListener {
5 | void onClick(View view);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/chap09_lambda_receiver_dsl/ViewCreator.kt:
--------------------------------------------------------------------------------
1 | package chap09_lambda_receiver_dsl
2 |
3 | class ViewCreator {
4 | class XMLChildContainer : XMLContainer() {
5 | private val tagData = StringBuilder()
6 |
7 | fun attr(attrName: String, value: String) {
8 | tagData.append(" $attrName=\"$value\"")
9 | }
10 |
11 | fun attrData() = tagData.toString()
12 | }
13 |
14 | open class XMLContainer {
15 | private val data = StringBuilder()
16 |
17 | fun child(tag: String, action: XMLChildContainer.() -> Unit): XMLContainer {
18 | data.append("<$tag")
19 | val tagData = XMLChildContainer()
20 | tagData.action()
21 | data.append(tagData.attrData())
22 | data.append(">")
23 | data.append(tagData.data())
24 | data.append("\n$tag>")
25 | return this
26 | }
27 |
28 | fun data() = data.toString()
29 | }
30 | }
31 |
32 | fun createAndroidLayout(): ViewCreator.XMLContainer {
33 | return ViewCreator.XMLContainer()
34 | }
35 |
36 | fun main(args: Array) {
37 | val xml = createAndroidLayout()
38 | .child("LinearLayout") {
39 | attr("android:layout_height", "match_parent")
40 | attr("android:layout_width", "match_parent")
41 | attr("android:orientation", "vertical")
42 | child("ImageView") {
43 | attr("android:layout_height", "match_parent")
44 | attr("android:layout_width", "match_parent")
45 | }
46 | child("TextView") {
47 | attr("android:layout_height", "match_parent")
48 | attr("android:layout_width", "match_parent")
49 | }
50 | }
51 | println(xml.data())
52 | }
--------------------------------------------------------------------------------
/src/chap10_elvis_operator/ElvisSyntax.kt:
--------------------------------------------------------------------------------
1 | package chap10_elvis_operator
2 |
3 | class ElvisSyntax {
4 | fun elvisSample(arg: String?) {
5 | val value = arg ?: ""
6 | }
7 | }
--------------------------------------------------------------------------------
/src/chap10_elvis_operator/ExpandedElvis.kt:
--------------------------------------------------------------------------------
1 | package chap10_elvis_operator
2 |
3 | class ExpandedElvis {
4 | fun elvisSample(arg: String?) {
5 | val value = if (arg != null) arg else ""
6 | }
7 | }
--------------------------------------------------------------------------------
/src/chap10_elvis_operator/SafeCall.kt:
--------------------------------------------------------------------------------
1 | package chap10_elvis_operator
2 |
3 | class SafeCall {
4 | data class Person(val name: String, val age: Int)
5 |
6 | fun safeCallTest() {
7 | val john: Person? = Person("John", 32)
8 |
9 | val age = john?.age
10 | // Uncomment to experience compile error
11 | //val offsetAge = age + 1 /* compile error */
12 | }
13 |
14 | fun elvisDefault() {
15 | val john: Person? = Person("John", 32)
16 |
17 | val age = john?.age ?: 25
18 | val offsetAge = age + 1 /* no compile error */
19 | }
20 |
21 | fun elvisThrow() {
22 | val john : Person? = Person("John", 32)
23 |
24 | val age = john?.age ?: throw IllegalArgumentException("John is null")
25 | val offsetAge = age + 1 /* no compile error */
26 | }
27 | }
--------------------------------------------------------------------------------
/src/chap11_property_delegation/Delegate.kt:
--------------------------------------------------------------------------------
1 | package chap11_property_delegation
2 |
3 | import kotlin.properties.ReadOnlyProperty
4 | import kotlin.reflect.KProperty
5 |
6 | class DelegateTest {
7 | val name: String by NameDelegate(Database())
8 | }
9 |
10 | class Database {
11 | fun queryName(): String = "Sample results"
12 | }
13 |
14 | class NameDelegate(private val db: Database) : ReadOnlyProperty {
15 | override fun getValue(thisRef: T, property: KProperty<*>): String = db.queryName()
16 | }
--------------------------------------------------------------------------------
/src/chap11_property_delegation/LazyTest.kt:
--------------------------------------------------------------------------------
1 | package chap11_property_delegation
2 |
3 | class LazyTest {
4 | data class Hero(val attribute: String, val attackType: String)
5 |
6 | val _hero: Hero by lazy { Hero("agility", "melee") }
7 | }
--------------------------------------------------------------------------------
/src/chap11_property_delegation/ManualLazy.kt:
--------------------------------------------------------------------------------
1 | package chap11_property_delegation
2 |
3 | class ManualLazy {
4 | data class Hero(val attribute: String, val attackType: String)
5 |
6 | private var _hero: Hero? = null
7 |
8 | val hero: Hero
9 | get() {
10 | if (_hero == null) {
11 | _hero = Hero("agility", "melee")
12 | }
13 | return _hero!!
14 | }
15 | }
--------------------------------------------------------------------------------
/src/chap11_property_delegation/ObservableTest.kt:
--------------------------------------------------------------------------------
1 | package chap11_property_delegation
2 |
3 | import kotlin.properties.Delegates
4 |
5 | class ObservableTest {
6 | data class Hero(val attribute: String, val attackType: String)
7 |
8 | var hero: Hero by Delegates.observable(Hero("agility", "melee")) { prop, old, new ->
9 | /* Do something here */
10 | }
11 | }
--------------------------------------------------------------------------------
/src/chap12_higher_order_function_and_function_type/FunctionType.kt:
--------------------------------------------------------------------------------
1 | package chap12_higher_order_function_and_function_type
2 |
3 |
4 | // A copy of stdlib function interface. Please check actual stdlib function for the updated code
5 | /** A function that takes 1 argument. */
6 | public interface Function1 : Function {
7 | /** Invokes the function with the specified argument. */
8 | public operator fun invoke(p1: P1): R
9 | }
--------------------------------------------------------------------------------
/src/chap13_inline/InlinedFilter.kt:
--------------------------------------------------------------------------------
1 | package chap13_inline
2 |
3 | class InlinedFilter {
4 | inline fun inlinedFilter(list: List, predicate: (Int) -> Boolean): List {
5 | return list.filter(predicate)
6 | }
7 |
8 | fun lambdaInCallSiteTest() {
9 | val list = listOf(1, 2, 3)
10 | val newList = inlinedFilter(list) { it < 2 }
11 | println(newList)
12 | }
13 | }
--------------------------------------------------------------------------------
/src/chap13_inline/InlinedFunctionReference.kt:
--------------------------------------------------------------------------------
1 | package chap13_inline
2 |
3 | class InlinedFunctionReference {
4 | inline fun inlinedFilter(list: List, predicate: (Int) -> Boolean): List {
5 | return list.filter(predicate)
6 | }
7 |
8 | fun filterLessThanTwo(input: Int) = input < 2
9 |
10 | fun functionReferenceTest() {
11 | val list = listOf(1, 2, 3)
12 | val newList = inlinedFilter(list, ::filterLessThanTwo)
13 | println(newList)
14 | }
15 | }
--------------------------------------------------------------------------------
/src/chap13_inline/LambdaInstance.kt:
--------------------------------------------------------------------------------
1 | package chap13_inline
2 |
3 | class LambdaInstance {
4 | inline fun inlinedFilter(list: List, predicate: (Int) -> Boolean): List {
5 | return list.filter(predicate)
6 | }
7 |
8 | fun filterLessThanTwo(input: Int) = input < 2
9 |
10 | fun lambdaInstance(predicate: (Int) -> Boolean) {
11 | val list = listOf(1, 2, 3)
12 | val newList = inlinedFilter(list, predicate)
13 | println(newList)
14 | }
15 |
16 | fun lambdaInstanceTest() {
17 | lambdaInstance(::filterLessThanTwo)
18 | }
19 | }
--------------------------------------------------------------------------------
/src/chap13_inline/NotInlinedFilter.kt:
--------------------------------------------------------------------------------
1 | package chap13_inline
2 |
3 | class NotInlinedFilter {
4 | fun notInlinedFilter(list: List, predicate: (Int) -> Boolean): List {
5 | return list.filter(predicate)
6 | }
7 |
8 | fun notInlinedTest() {
9 | val list = listOf(1, 2, 3)
10 | val newList = notInlinedFilter(list) { it < 2 }
11 | println(newList)
12 | }
13 | }
--------------------------------------------------------------------------------
/src/chap14_lambda_and_control_flows/AnonymousFunctionReturns.kt:
--------------------------------------------------------------------------------
1 | package chap14_lambda_and_control_flows
2 |
3 | class AnonymousFunctionReturns {
4 | data class Student(val name: String, val id: Int)
5 |
6 | private fun findSpock(list: List) {
7 | list.forEach(fun(student) {
8 | if (student.name == "Spock") {
9 | println("Found Spock")
10 | return
11 | }
12 | })
13 | println("Did we find Spock?")
14 | }
15 |
16 | fun findStudentTest() {
17 | val studentList = listOf(Student("Kirk", 12345), Student("Spock", 54321))
18 | findSpock(studentList)
19 | println("End of findStudentTest")
20 | }
21 | }
22 |
23 | fun main(args: Array) {
24 | val test = AnonymousFunctionReturns()
25 | test.findStudentTest()
26 | }
--------------------------------------------------------------------------------
/src/chap14_lambda_and_control_flows/InlineReturn.kt:
--------------------------------------------------------------------------------
1 | package chap14_lambda_and_control_flows
2 |
3 | class InlineReturn {
4 | data class Student(val name: String, val id: Int)
5 |
6 | private inline fun findSpock(list: List, func: (Student) -> Unit) {
7 | list.forEach { func(it) }
8 | println("Did we find Spock?")
9 | }
10 |
11 | fun findStudentTest() {
12 | val studentList = listOf(Student("Kirk", 12345), Student("Spock", 54321))
13 | findSpock(studentList) {
14 | if (it.name == "Spock") {
15 | println("Found Spock")
16 | return
17 | }
18 | println("Not Spock")
19 | }
20 | println("End of findStudentTest")
21 | }
22 | }
23 |
24 | fun main(args: Array) {
25 | val test = InlineReturn()
26 | test.findStudentTest()
27 | }
--------------------------------------------------------------------------------
/src/chap14_lambda_and_control_flows/LambdaReturn.kt:
--------------------------------------------------------------------------------
1 | package chap14_lambda_and_control_flows
2 |
3 | class LambdaReturn {
4 | data class Student(val name: String, val id: Int)
5 |
6 | private fun findSpock(list: List) {
7 | list.forEach {
8 | if (it.name == "Spock") {
9 | println("Found Spock")
10 | return
11 | }
12 | }
13 | println("Spock not found")
14 | }
15 |
16 | fun findStudentTest() {
17 | val studentList = listOf(Student("Kirk", 12345), Student("Spock", 54321))
18 | findSpock(studentList)
19 | println("End of findStudentTest")
20 | }
21 | }
22 |
23 | fun main(args: Array) {
24 | val test = LambdaReturn()
25 | test.findStudentTest()
26 | }
--------------------------------------------------------------------------------
/src/chap14_lambda_and_control_flows/NotinlineLambdaReturn.kt:
--------------------------------------------------------------------------------
1 | package chap14_lambda_and_control_flows
2 |
3 | fun higherOrderFunction(lambda : () -> Unit) {
4 | }
5 |
6 | fun lambdaReturnTest() {
7 | higherOrderFunction(fun() {
8 | return
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/chap14_lambda_and_control_flows/ReturnWithLabels.kt:
--------------------------------------------------------------------------------
1 | package chap14_lambda_and_control_flows
2 |
3 | class ReturnWithLabels {
4 | data class Student(val name: String, val id: Int)
5 |
6 | private fun findSpock(list: List) {
7 | list.forEach label@{
8 | // or simply omit and use return@foreach instead
9 | if (it.name == "Spock") {
10 | println("Found Spock")
11 | return@label
12 | }
13 | }
14 | println("Did we find Spock?")
15 | }
16 |
17 | fun findStudentTest() {
18 | val studentList = listOf(Student("Kirk", 12345), Student("Spock", 54321))
19 | findSpock(studentList)
20 | println("End of findStudentTest")
21 | }
22 | }
23 |
24 | fun main(args: Array) {
25 | val test = ReturnWithLabels()
26 | test.findStudentTest()
27 | }
--------------------------------------------------------------------------------
/src/chap15_reified_parameters/ReifiedParameter.kt:
--------------------------------------------------------------------------------
1 | package chap15_reified_parameters
2 |
3 | inline fun doSomethingWithType(obj: T) {
4 | val typeName = T::class.java
5 | println(typeName)
6 | }
7 |
8 | fun main(args: Array) {
9 | doSomethingWithType(String())
10 | }
--------------------------------------------------------------------------------
/src/chap15_reified_parameters/TypeErasure.kt:
--------------------------------------------------------------------------------
1 | package chap15_reified_parameters
2 |
3 | fun getCount(list : List) : Int = list.size
--------------------------------------------------------------------------------
/src/chap15_reified_parameters/TypeErasureLimitation.kt:
--------------------------------------------------------------------------------
1 | package chap15_reified_parameters
2 |
3 | fun isListOfString(arg: T): Boolean {
4 | // Uncomment to experience compile error
5 | //return arg is List // Compile error
6 | return true
7 | }
8 |
9 | fun isList(arg: T): Boolean {
10 | return arg is List<*>
11 | }
--------------------------------------------------------------------------------
/src/chap16_noinline_crossinline/Crossinline.kt:
--------------------------------------------------------------------------------
1 | package chap16_noinline_crossinline
2 |
3 | fun someHigherOrderFunction(message: String, func: (String) -> Unit) {
4 | }
5 |
6 | inline fun crossInlineTest(message: String, crossinline func: (String) -> Unit) {
7 | someHigherOrderFunction("crossInlineTest") {
8 | func(it) // Compile error here
9 | }
10 | }
11 |
12 | fun main(arg: Array) {
13 | someHigherOrderFunction("Hello") {
14 | println(it)
15 | // Uncomment to experience compile error
16 | //return // Compile error here because crossinline does not allow return
17 | }
18 | println("Main finished")
19 | }
20 |
--------------------------------------------------------------------------------
/src/chap16_noinline_crossinline/Noinline.kt:
--------------------------------------------------------------------------------
1 | package chap16_noinline_crossinline
2 |
3 | inline fun doSomething(obj: T, noinline func: (T) -> T) {
4 | func(obj)
5 | }
6 |
7 | fun main(args: Array) {
8 | doSomething(String()) { it }
9 | }
--------------------------------------------------------------------------------
/src/chap16_noinline_crossinline/Safidfngd.java:
--------------------------------------------------------------------------------
1 | package chap16_noinline_crossinline;
2 |
3 | import kotlin.jvm.functions.Function1;
4 | import kotlin.jvm.internal.Intrinsics;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | public class Safidfngd {
8 | private static final void doSomething(Object obj, Function1 func) {
9 | func.invoke(obj);
10 | }
11 |
12 | public static final void main(@NotNull String[] args) {
13 | Intrinsics.checkParameterIsNotNull(args, "args");
14 | String obj$iv = new String();
15 | Function1 func$iv = (Function1) new Function1() {
16 | @Override
17 | public String invoke(String s) {
18 | return s;
19 | }
20 | };
21 | func$iv.invoke(obj$iv);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/chap17_variance/Contravariance.java:
--------------------------------------------------------------------------------
1 | package chap17_variance;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class Contravariance {
7 | public static void main(String... args) {
8 | varianceTest();
9 | }
10 |
11 | public static void varianceTest() {
12 | List numbers = new ArrayList<>();
13 | genericVariance(numbers);
14 |
15 | List