Kotlin In-depth [Vol-II]: A comprehensive guide to modern multi-paradigm language
()
About this ebook
The book starts with an introduction to language and its ecosystem that will give you an understanding of the key ideas behind Kotlin design, introduce you to Kotlin tooling and present you the basic language syntax and constructs. In the next chapters we’ll get to know the multi-paradigm nature of Kotlin which allows you to create powerful abstractions by combining various aspects of functional and object-oriented programming. We’ll talk about using common Kotlin APIs such as the standard library, reflection, and coroutine-based concurrency as well as the means for creating your own flexible APIs based on domain-specific languages. In the concluding chapters, we’ll give examples of using Kotlin for more specialized tasks such as testing, building Android applications, Web development and creating microservices.
Read more from Aleksei Sedunov
Kotlin In-Depth: A Guide to a Multipurpose Programming Language for Server-Side, Front-End, Android, and Multiplatform Mobile Rating: 5 out of 5 stars5/5Kotlin In-Depth [Vol-I]: A Comprehensive Guide to Modern Multi-Paradigm Language Rating: 0 out of 5 stars0 ratings
Related to Kotlin In-depth [Vol-II]
Related ebooks
Kotlin at a Glance: Use of Lambdas and higher-order functions to write more concise, clean, reusable, and simple code Rating: 0 out of 5 stars0 ratingsGo Programming Blueprints Rating: 0 out of 5 stars0 ratingsAsynchronous Android Programming - Second Edition Rating: 0 out of 5 stars0 ratingsLearning ClojureScript Rating: 0 out of 5 stars0 ratingsAtomic Kotlin Rating: 0 out of 5 stars0 ratingsJavaScript at Scale Rating: 0 out of 5 stars0 ratingsFunctional Programming in C#, Second Edition Rating: 0 out of 5 stars0 ratingsJava 8 to 21: Explore and work with the cutting-edge features of Java 21 (English Edition) Rating: 0 out of 5 stars0 ratingsBeginning Mobile Application Development in the Cloud Rating: 0 out of 5 stars0 ratingsExploring Web Components: Build Reusable UI Web Components with Standard Technologies (English Edition) Rating: 0 out of 5 stars0 ratingsAndroid application development with Kotlin: Build Your First Android App In No Time Rating: 0 out of 5 stars0 ratingsDesigning Microservices using Django: Structuring, Deploying and Managing the Microservices Architecture with Django Rating: 0 out of 5 stars0 ratingsObject Oriented Programming with Angular: Build and Deploy Your Web Application Using Angular with Ease ( English Edition) Rating: 0 out of 5 stars0 ratingsPro Spring Boot 2: An Authoritative Guide to Building Microservices, Web and Enterprise Applications, and Best Practices Rating: 0 out of 5 stars0 ratingsRust for C++ Programmers: Learn how to embed Rust in C/C++ with ease (English Edition) Rating: 0 out of 5 stars0 ratingsDependency Injection: Design patterns using Spring and Guice Rating: 0 out of 5 stars0 ratingsScala Functional Programming Patterns Rating: 0 out of 5 stars0 ratingsiOS in Practice Rating: 0 out of 5 stars0 ratingsAndroid Studio Electric Eel Essentials - Kotlin Edition: Developing Android Apps Using Android Studio 2022.1.1 and Kotlin Rating: 0 out of 5 stars0 ratingsJava 9 with JShell Rating: 0 out of 5 stars0 ratingsD Cookbook Rating: 0 out of 5 stars0 ratingsProgramming Kotlin Applications: Building Mobile and Server-Side Applications with Kotlin Rating: 0 out of 5 stars0 ratingsLearning Concurrent Programming in Scala Rating: 0 out of 5 stars0 ratingsBuilding Python Real-Time Applications with Storm Rating: 0 out of 5 stars0 ratingsMastering Computer Programming Rating: 0 out of 5 stars0 ratingsJulia as a Second Language Rating: 0 out of 5 stars0 ratingsBluetooth Low Energy LE Complete Self-Assessment Guide Rating: 0 out of 5 stars0 ratings
Programming For You
Python: For Beginners A Crash Course Guide To Learn Python in 1 Week Rating: 4 out of 5 stars4/5HTML & CSS: Learn the Fundaments in 7 Days Rating: 4 out of 5 stars4/5Python Programming : How to Code Python Fast In Just 24 Hours With 7 Simple Steps Rating: 4 out of 5 stars4/5Java for Beginners: A Crash Course to Learn Java Programming in 1 Week Rating: 5 out of 5 stars5/5SQL: For Beginners: Your Guide To Easily Learn SQL Programming in 7 Days Rating: 5 out of 5 stars5/5Coding All-in-One For Dummies Rating: 4 out of 5 stars4/5Python Machine Learning By Example Rating: 4 out of 5 stars4/5Learn to Code. Get a Job. The Ultimate Guide to Learning and Getting Hired as a Developer. Rating: 5 out of 5 stars5/5Learn SQL in 24 Hours Rating: 5 out of 5 stars5/5SQL QuickStart Guide: The Simplified Beginner's Guide to Managing, Analyzing, and Manipulating Data With SQL Rating: 4 out of 5 stars4/5Linux: Learn in 24 Hours Rating: 5 out of 5 stars5/5Pokemon Go: Guide + 20 Tips and Tricks You Must Read Hints, Tricks, Tips, Secrets, Android, iOS Rating: 5 out of 5 stars5/5Excel : The Ultimate Comprehensive Step-By-Step Guide to the Basics of Excel Programming: 1 Rating: 5 out of 5 stars5/5Grokking Algorithms: An illustrated guide for programmers and other curious people Rating: 4 out of 5 stars4/5SQL All-in-One For Dummies Rating: 3 out of 5 stars3/5Modern C++ for Absolute Beginners: A Friendly Introduction to C++ Programming Language and C++11 to C++20 Standards Rating: 0 out of 5 stars0 ratingsWeb Designer's Idea Book, Volume 4: Inspiration from the Best Web Design Trends, Themes and Styles Rating: 4 out of 5 stars4/5101 Amazing Nintendo NES Facts: Includes facts about the Famicom Rating: 4 out of 5 stars4/5OneNote: The Ultimate Guide on How to Use Microsoft OneNote for Getting Things Done Rating: 1 out of 5 stars1/5Learn PowerShell in a Month of Lunches, Fourth Edition: Covers Windows, Linux, and macOS Rating: 0 out of 5 stars0 ratings
Reviews for Kotlin In-depth [Vol-II]
0 ratings0 reviews
Book preview
Kotlin In-depth [Vol-II] - Aleksei Sedunov
Kotlin In-Depth
[Vol. II]
A Comprehensive Guide to
Modern Multi-Paradigm Language
by
Aleksei Sedunov
FIRST EDITION 2020
Copyright © BPB Publications, India
ISBN: 978-93-89423-228
All Rights Reserved. No part of this publication may be reproduced or distributed in any form or by any means or stored in a database or retrieval system, without the prior written permission of the publisher with the exception to the program listings which may be entered, stored and executed in a computer system, but they can not be reproduced by the means of publication.
LIMITS OF LIABILITY AND DISCLAIMER OF WARRANTY
The information contained in this book is true to correct and the best of author’s & publisher’s knowledge. The author has made every effort to ensure the accuracy of these publications, but cannot be held responsible for any loss or damage arising from any information in this book.
All trademarks referred to in the book are acknowledged as properties of their respective owners.
Distributors:
BPB PUBLICATIONS
20, Ansari Road, Darya Ganj
New Delhi-110002
Ph: 23254990/23254991
MICRO MEDIA
Shop No. 5, Mahendra Chambers,
150 DN Rd. Next to Capital Cinema,
V.T. (C.S.T.) Station, MUMBAI-400 001
Ph: 22078296/22078297
DECCAN AGENCIES
4-3-329, Bank Street,
Hyderabad-500195
Ph: 24756967/24756400
BPB BOOK CENTRE
376 Old Lajpat Rai Market,
Delhi-110006
Ph: 23861747
Published by Manish Jain for BPB Publications, 20 Ansari Road, Darya Ganj, New Delhi-110002 and Printed by him at Repro India Ltd, Mumbai
Dedicated to
Tatiana, my guiding light
and the incessant source of inspiration
About the Author
Aleksei Sedunov has been working as a Java developer since 2008. After joining JetBrains in 2012 he’s been actively participating in the Kotlin language development focusing on IDE tooling for the IntelliJ platform. Currently he’s working in a DataGrip team, a JetBrains Database IDE, carrying on with using Kotlin as a main development tool.
Acknowledgement
Above all others I would like to give my gratitude to the entire Kotlin team at JetBrains which has created such a beautiful language and continues to relentlessly work on its improvement – especially Andrey Breslav who’s been leading the language design from the very first day.
I’m really grateful to everyone at BPB publications for giving me this splendid opportunity for writing this book and lending a tremendous support in improving the text before it gets to the readers.
Last but not least I’d like to thank my beloved family for their support throughout the work on the book.
– Aleksei Sedunov
Preface
Since its first release in 2016 (and even long before that) Kotlin has been gaining in popularity as a powerful and flexible tool in a multitude of development tasks being equally well-equipped for dealing with mobile, desktop and server-side applications finally getting its official acknowledgment from Google in 2017 and 2018 as a primary language for Android development. This popularity is well-justified since language pragmatism, the tendency to choose the best practice among known solutions was one of the guiding principles of its design.
With the book you’re holding in your hands I’d like to invite you to the beautiful world of Kotlin programming where you can see its benefits for yourself. After completing this book you’ll have all the necessary knowledge to write in Kotlin on your own.
The second volume introduces you to the more advanced Kotlin features such as reflection, domain-specific languages and coroutines, discusses Java/Kotlin interoperability issues and explains how Kotlin can be used in various development areas, including testing, Android applications and Web. It’s divided into the following 8 chapters:
Chapter 10 addresses the use of annotations which allow you to accompany Kotlin code with various metadata and explains the basics of Reflection API which provides access to runtime representation of Kotlin declarations.
Chapter 11 describes some advanced features which help developer in composing flexible APIs in a form of the domain-specific languages: operator overloading, delegated properties and builder-style DSLs based on the higher-order functions.
Chapter 12 discusses common issues of combining Java and Kotlin code within the same codebase and explain the specifics of using Java declarations in Kotlin code and vice versa.
Chapter 13 introduces the reader to the Kotlin coroutines library which inroduces a set of building blocks for programming asynchronous computations. Additionally it describes some utilities simplifying the use of Java concurrency API in Kotlin code.
Chapter 14 is devoted to the KotlinTest, a popular testing framework aimed specifically at the Kotlin developers. It describes various specification styles, explains the use of assertion API and addresses more advanced issues like using fixtures and test configurations.
Chapter 15 serves as an introduction to using Kotlin for development on the Android platform. It guides the reader through setting up an Android Studio project and explains basic aspects of Android development on an example of a simple calculator application.
Chapter 16 explains the basic features of the Ktor framework aimed at development of connected applications which make heavy use of Kotlin featutes and asynchronous computations.
Chapter 17 describes how to build a microservice application using Spring Boot and Ktor frameworks.
Downloading the code
bundle and coloured images:
Please follow the link to download the
Code Bundle and the Coloured Images of the book:
https://rebrand.ly/rrq2rot
Errata
We take immense pride in our work at BPB Publications and follow best practices to ensure the accuracy of our content to provide with an indulging reading experience to our subscribers. Our readers are our mirrors, and we use their inputs to reflect and improve upon human errors if any, occurred during the publishing processes involved. To let us maintain the quality and help us reach out to any readers who might be having difficulties due to any unforeseen errors, please write to us at :
errata@bpbonline.com
Your support, suggestions and feedbacks are highly appreciated by the BPB Publications’ Family.
Table of Contents
10. Annotations and Reflection
Structure
Objective
Annotations
Defining and using annotation classes
Built-in annotations
Reflection
Reflection API overview
Classifiers and types
Callables
Conclusion
Questions
11. Domain-Specific Languages
Structure
Objective
Operator overloading
Unary operations
Increments and decrements
Binary operations
Infix operations
Assignments
Invocations and indexing
Destructuring
Iteration
Delegated properties
Standard delegates
Creating custom delegates
Delegate representation
Higher-order functions and DSLs
Fluent DSL with infix functions
Using type-safe builders
@DslMarker
Conclusion
Questions
12. Java Interoperability
Structure
Objectives
Using the Java code from Kotlin
Java methods and fields
Unit vs void
Operator conventions
Synthetic properties
Platform types
Nullability annotations
Java/Kotlin type mapping
Single abstract method interfaces
Using Java to Kotlin converter
Using the Kotlin code from Java
Accessing properties
File facades and top-level declarations
Objects and static members
Changing the exposed declaration name
Generating overloads
Declaring exceptions
Inline functions
Type aliases
Conclusion
Questions
13. Concurrency
Structure
Objective
Coroutines
Coroutines and suspending functions
Coroutine builders
Coroutine scopes and structured concurrency
Coroutine context
Coroutine control flow
Job lifecycle
Cancellation
Timeouts
Coroutine dispatching
Exception handling
Concurrent communication
Channels
Producers
Tickers
Actors
Using Java concurrency
Starting a thread
Synchronization and locks
Conclusion
Questions
14. Testing with Kotlin
Structure
Objective
KotlinTest specifications
Getting started with KotlinTest
Specification styles
Assertions
Matchers
Inspectors
Handling exceptions
Testing non-deterministic code
Property-based testing
Fixtures and configurations
Providing a fixture
Test configuration
Conclusion
Questions
15. Android Applications
Structure
Objective
Getting started with Android
Setting up an Android Studio project
Gradle build scripts
Activity
Using an Emulator
Activities
Designing the application UI
Implementing the activity class
Kotlin Android Extensions
Preserving the activity state
Anko Layouts
Conclusion
Questions
16. Web Development with Ktor
Structure
Objective
Introducing Ktor
Server features
Routing
Handling HTTP requests
HTML DSL
Sessions support
Client features
Requests and responses
Cookies
Conclusion
Questions
17. Building Microservices
Structure
Objectives
The microservice architecture
Introducing Spring Boot
Setting up a project
Deciding on the Services API
Implementing a random generator service
Implementing a password generator service
Microservices with Ktor
Using the JSON serialization feature
Implementing a password generator service
Conclusion
Questions
CHAPTER 10
Annotations and Reflection
In this chapter, we will be covering two major topics. The first part will be devoted to annotations, which allow you to bind metadata to Kotlin declarations and access them later, at runtime. We will explain how to define and apply your own annotations and look at some built-in annotations, which affect the compilation of the Kotlin source code.
The second part will introduce us to the Reflection API, which defines a set of types comprising runtime representation of Kotlin declarations. We’ll discuss how to obtain reflection objects, access their attributes and use callables, to dynamically invoke functions and properties.
Structure
Defining and using annotation classes
Built-in annotations
Class literals and callable references
Reflection API
Objective
Learn to apply annotations in Kotlin source code, as well as, declare your own annotation classes. Get an understanding of how to use Kotlin Reflection API to obtain runtime information about Kotlin declarations, and dynamically invoke functions and properties.
Annotations
Annotation is a special kind of Kotlin class that allows you to define custom metadata and bind them to the elements of your source code - declarations, expressions or whole files. Like their Java counterparts, Kotlin annotations can be accessed at runtime. This ability is used extensively by various frameworks and processing tools, which rely on annotations for configuration and code instrumentation purposes.
Defining and using annotation classes
The syntax of annotation usage is rather similar to that of Java. The most basic case is annotating a declaration when you put a @-prefixed annotation name into its modifier list. For example, when using test framework, such as JUnit, you can mark test methods using annotation @Test:
class MyTestCase {
@Test
fun testOnePlusOne() {
assert(1 + 1 == 2)
}
}
Java vs. Kotlin: Unlike Java, some Kotlin annotations may also be applied to expressions. For example, the built-in @Suppress annotation can be used to suppress the compiler warnings for a particular expression in the source file:
val s = @Suppress(UNCHECKED_CAST
) objects as List
If you have multiple annotations for the same source file element, then you may group them inside square brackets:
@[Synchronized Strictfp] // the same as @Synchronized @Strictfp
fun main() { }
If you want to apply annotation to a primary constructor, then you need to use an explicit constructor keyword:
class A @MyAnnotation constructor ()
In Chapter 4 (Working with Classes and Objects), we have already used similar syntax to make a primary constructor private.
To define an annotation, you have to declare a class marked with a special annotation modifier:
annotation class MyAnnotation
@MyAnnotation fun annotatedFun() { }
Java vs. Kotlin: Please note the difference between the annotation definitions in Kotlin and Java. While Java annotations have a syntactic form of an interface, Kotlin annotations comprise a special kind of class.
Unlike ordinary classes, annotation classes may not have members, secondary constructors or initializers:
annotation class MyAnnotation {
val text = ???
// Error
}
However, since Kotlin 1.3, you can add nested classes, interfaces and objects (including companions) to the annotation body:
annotation class MyAnnotation {
companion object {
val text = ???
}
}
If you want to add custom attributes to your annotation, you may do so via constructor parameters. When an annotation like this is used, you need to provide the actual values for the parameters like a class constructor call:
annotation class MyAnnotation(val text: String)
@MyAnnotation(Some useful info
) fun annotatedFun() { }
Please note, that the annotation parameters must always be marked as val.
Java vs. Kotlin: It is worth remembering that Java annotation attributes are specified in a form of parameter-less methods. However, in Kotlin, you use constructor parameters that also play the role of properties.
Similarly to ordinary constructors you may use default values and varargs:
annotation class Dependency(var arg val componentNames: String)
annotation class Component(val name: String = Core
)
@Component(I/O
)
class IO
@Component(Log
)
@Dependency(I/O
)
class Logger
@Component
@Dependency(I/O
, Log
)
class Main
Even though every Kotlin annotation is a kind of a class, you cannot instantiate them the way you do with ordinary classes:
annotation class Component(val name: String = Core
)
val ioComponent = Component(IO
) // Error
Annotations can only be constructed using @ syntax, as mentioned above. To retrieve an actual annotation instance (if it’s preserved at runtime), you may use Reflection API, which we will discuss in the upcoming sections.
Annotation classes cannot have explicit supertypes and cannot be inherited. They automatically inherit from the Any class and empty Annotation interface, which serves as a common supertype for all annotation classes.
Since annotation arguments are evaluated at the compilation time, you may not place arbitrary computations there. Furthermore, the compiler limits the range of possible types that you may use for annotation parameters:
Primitive types such as Int, Boolean or Double;
String;
Enums;
Other annotations;
Class literals;
Arrays of the types above.
Please note, that a parameter like this may not be nullable, because JVM does not allow you to store nulls in annotation attributes.
When you use another annotation as an argument, you do not have to put @ prefix before its name. Instead, you write the annotation like an ordinary constructor call. Let us rework our previous example a little:
annotation class Dependency(vararg val componentNames: String)
annotation class Component(
val name: String = Core
,
val dependency: Dependency = Dependency()
)
@Component(I/O
)
class IO
@Component(Log
, Dependency(I/O
))
class Logger
@Component(dependency = Dependency(I/O
, Log
))
class Main
Annotation parameters may have an explicit array type without using a vararg. When using an annotation like this, you may construct an array using the standard arrayOf() function:
annotation class Dependency(val componentNames: Array
@Component(dependency = Dependency(arrayOf(I/O
, Log
)))
class Main
Since Kotlin 1.2, you may also use a more concise syntax by enclosing the array elements inside square brackets:
annotation class Dependency(val componentNames: Array
@Component(dependency = Dependency([I/O
, Log
]))
class Main
Such array literals are currently only supported inside annotations.
Class literal gives you a representation of a class as a reflection object of type KClass. This type serves as a Kotlin counterpart of the Class type used in the Java language. The class literal consists of a class name followed by ::class. Let us modify our component/depedency example to use class literals instead of names:
import kotlin.reflect.KClass
annotation class Dependency(vararg val componentClasses: KClass<*>)
annotation class Component(
val name: String = Core
,
val dependency: Dependency = Dependency()
)
@Component(I/O
)
class IO
@Component(Log
, Dependency(IO::class))
class Logger
@Component(dependency = Dependency(IO::class, Logger::class))
class Main
Java vs. Kotlin: Please note that instances of java.lang.Class may not be used in Kotlin annotations. However, during the JVM-targeted compilation Kotlin class literals are automatically converted into Java’s.
There are cases when a single declaration in a Kotlin source file corresponds to multiple language elements that may have annotations. For example, suppose that we have the following class:
class Person(val name: String)
The val name: String in the code above serves as a shorthand declaration for a constructor parameter, a class property with getter and a backing field that is used to store a property value. Since each of those elements may have their own annotations, Kotlin allows you to specify a particular annotation target at its use site.
The use-site target is represented by a special keyword, which is placed before the annotation name and is separated by the : character. For example, if we want to place some annotation on a property getter, then we use the get keyword:
class Person(@get:A val name: String)
Most of the use-site targets are related to various components of a property. Such targets can be applied to any top-level or class property, as well as, the val/var parameter of a primary constructor:
property: represents a property itself;
field: represents the backing field (applicable only to properties that have a backing field);
get: represents property getter;
set: represents property setter (applicable only to mutable properties);
param: represents the constructor parameter (applicable only to val/var parameters);
setparam: represents the parameter of a property setter (applicable only to mutable properties);
delegate: represents the field that stores a delegate object (applicable only to a delegated property, see Chapter 11, Domain-Specific Languages, for details);
The get/set targets allow you to annotate property accessors even when they are not explicitly present in your code (like val parameter in the example above). The same stands true for the setparam target, which has the same effect as the annotation setter parameter directly.
Annotations with use-site target can be also be grouped using the [] syntax. In