Discover millions of ebooks, audiobooks, and so much more with a free trial

Only $11.99/month after trial. Cancel anytime.

Kotlin In-depth [Vol-II]: A comprehensive guide to modern multi-paradigm language
Kotlin In-depth [Vol-II]: A comprehensive guide to modern multi-paradigm language
Kotlin In-depth [Vol-II]: A comprehensive guide to modern multi-paradigm language
Ebook418 pages3 hours

Kotlin In-depth [Vol-II]: A comprehensive guide to modern multi-paradigm language

Rating: 0 out of 5 stars

()

Read preview

About this ebook

The purpose of this book is to guide a reader through the capabilities of the Kotlin language and give examples of using it for development of various applications be it desktop, mobile or Web. Although our primary focus is on the JVM and Android, the knowledge we’re sharing here to various extents applies to other Kotlin-supported platforms such as JavaScript, native and even multi-platform applications.
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.
LanguageEnglish
Release dateMar 7, 2020
ISBN9789389423235
Kotlin In-depth [Vol-II]: A comprehensive guide to modern multi-paradigm language

Read more from Aleksei Sedunov

Related to Kotlin In-depth [Vol-II]

Related ebooks

Programming For You

View More

Related articles

Reviews for Kotlin In-depth [Vol-II]

Rating: 0 out of 5 stars
0 ratings

0 ratings0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    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

    Enjoying the preview?
    Page 1 of 1