Kotlin in Action. 2 Ed

Kotlin in Action. 2 Ed

Kotlin in Action. 2 Ed
Автор: Aigner Sebastian, Elizarov Roman, Isakova Svetlana, Jemerov Dmitry
Дата выхода: 2024
Издательство: Manning Publications Co.
Количество страниц: 849
Размер файла: 4,7 МБ
Тип файла: PDF
Добавил: codelibs
 Проверить на вирусы  Дополнительные материалы 

Praise for the first edition
Kotlin in Action
Copyright
contents
front matter
preface
acknowledgments
about this book
Who should read this book
How this book is organized: A road map
About the code
liveBook discussion forum
Other online resources
about the authors
about the cover illustration
Part 1 Introducing Kotlin
1 Kotlin: What and why
1.1 A taste of Kotlin
1.2 Kotlin’s primary traits
1.2.1 Kotlin use cases: Android, server side, anywhere Java runs, and beyond
1.2.2 Static typing makes Kotlin performant, reliable, and maintainable
1.2.3 Combining functional and object-oriented programming makes Kotlin safe and flexible
1.2.4 Concurrent and asynchronous code becomes natural and structured with coroutines
1.2.5 Kotlin can be used for any purpose: It’s free, open source, and open to contributions
1.3 Areas in which Kotlin is often used
1.3.1 Powering backends: Server-side development with Kotlin
1.3.2 Mobile Development: Android is Kotlin first
1.3.3 Multiplatform: Sharing business logic and minimizing duplicate work on iOS, JVM, JS, and beyond
1.4 The philosophy of Kotlin
1.4.1 Kotlin is a pragmatic language
1.4.2 Kotlin is concise
1.4.3 Kotlin is safe
1.4.4 Kotlin is interoperable
1.5 Using the Kotlin tools
1.5.1 Setting up and running the Kotlin code
1.5.2 Compiling Kotlin code
Summary
2 Kotlin basics
2.1 Basic elements: Functions and variables
2.1.1 Writing your first Kotlin program: “Hello, world!”
2.1.2 Declaring functions with parameters and return values
2.1.3 Making function definitions more concise by using expression bodies
2.1.4 Declaring variables to store data
2.1.5 Marking a variable as read only or reassignable
2.1.6 Easier string formatting: String templates
2.2 Encapsulating behavior and data: Classes and properties
2.2.1 Associating data with a class and making it accessible: Properties
2.2.2 Computing properties instead of storing their values: Custom accessors
2.2.3 Kotlin source code layout: Directories and packages
2.3 Representing and handling choices: Enums and when
2.3.1 Declaring enum classes and enum constants
2.3.2 Using the when expression to deal with enum classes
2.3.3 Capturing the subject of a when expression in a variable
2.3.4 Using the when expression with arbitrary objects
2.3.5 Using the when expression without an argument
2.3.6 Smart casts: Combining type checks and casts
2.3.7 Refactoring: Replacing an if with a when expression
2.3.8 Blocks as branches of if and when
2.4 Iterating over things: while and for loops
2.4.1 Repeating code while a condition is true: The while loop
2.4.2 Iterating over numbers: Ranges and progressions
2.4.3 Iterating over maps
2.4.4 Using in to check collection and range membership
2.5 Throwing and catching exceptions in Kotlin
2.5.1 Handling exceptions and recovering from errors: try, catch, and finally
2.5.2 Using try as an expression
Summary
3 Defining and calling functions
3.1 Creating collections in Kotlin
3.2 Making functions easier to call
3.2.1 Named arguments
3.2.2 Default parameter values
3.2.3 Getting rid of static utility classes: Top-level functions and properties
3.3 Adding methods to other people’s classes: Extension functions and properties
3.3.1 Imports and extension functions
3.3.2 Calling extension functions from Java
3.3.3 Utility functions as extensions
3.3.4 No overriding for extension functions
3.3.5 Extension properties
3.4 Working with collections: varargs, infix calls, and library support
3.4.1 Extending the Java collections API
3.4.2 Varargs: Functions that accept an arbitrary number of arguments
3.4.3 Working with pairs: Infix calls and destructuring declarations
3.5 Working with strings and regular expressions
3.5.1 Splitting strings
3.5.2 Regular expressions and triple-quoted strings
3.5.3 Multiline triple-quoted strings
3.6 Making your code tidy: Local functions and extensions
Summary
4 Classes, objects, and interfaces
4.1 Defining class hierarchies
4.1.1 Interfaces in Kotlin
4.1.2 Open, final, and abstract modifiers: Final by default
4.1.3 Visibility modifiers: Public by default
4.1.4 Inner and nested classes: Nested by default
4.1.5 Sealed classes: Defining restricted class hierarchies
4.2 Declaring a class with nontrivial constructors or properties
4.2.1 Initializing classes: Primary constructor and initializer blocks
4.2.2 Secondary constructors: Initializing the superclass in different ways
4.2.3 Implementing properties declared in interfaces
4.2.4 Accessing a backing field from a getter or setter
4.2.5 Changing accessor visibility
4.3 Compiler-generated methods: Data classes and class delegation
4.3.1 Universal object methods
4.3.2 Data classes: Autogenerated implementations of universal methods
4.3.3 Class delegation: Using the by keyword
4.4 The object keyword: Declaring a class and creating an instance, combined
4.4.1 Object declarations: Singletons made easy
4.4.2 Companion objects: A place for factory methods and static members
4.4.3 Companion objects as regular objects
4.4.4 Object expressions: Anonymous inner classes rephrased
4.5 Extra type safety without overhead: Inline classes
Summary
5 Programming with lambdas
5.1 Lambda expressions and member references
5.1.1 Introduction to lambdas: Blocks of code as values
5.1.2 Lambdas and collections
5.1.3 Syntax for lambda expressions
5.1.4 Accessing variables in scope
5.1.5 Member references
5.1.6 Bound callable references
5.2 Using Java functional interfaces: Single abstract methods
5.2.1 Passing a lambda as a parameter to a Java method
5.2.2 SAM constructors: Explicit conversion of lambdas to functional interfaces
5.3 Defining SAM interfaces in Kotlin: fun interfaces
5.4 Lambdas with receivers: with, apply, and also
5.4.1 Performing multiple operations on the same object: with
5.4.2 Initializing and configuring objects: The apply function
5.4.3 Performing additional actions with an object: also
Summary
6 Working with collections and sequences
6.1 Functional APIs for collections
6.1.1 Removing and transforming elements: filter and map
6.1.2 Accumulating values for collections: reduce and fold
6.1.3 Applying a predicate to a collection: all, any, none, count, and find
6.1.4 Splitting a list into a pair of lists: partition
6.1.5 Converting a list to a map of groups: groupBy
6.1.6 Transforming collections into maps: associate, associateWith, and associateBy
6.1.7 Replacing elements in mutable collections: replaceAll and fill
6.1.8 Handling special cases for collections: ifEmpty
6.1.9 Splitting collections: chunked and windowed
6.1.10 Merging collections: zip
6.1.11 Processing elements in nested collections: flatMap and flatten
6.2 Lazy collection operations: Sequences
6.2.1 Executing sequence operations: Intermediate and terminal operations
6.2.2 Creating sequences
Summary
7 Working with nullable values
7.1 Avoiding NullPointerExceptions and handling the absence of values: Nullability
7.2 Making possibly null variables explicit with nullable types
7.3 Taking a closer look at the meaning of types
7.4 Combining null checks and method calls with the safe call operator: ?.
7.5 Providing default values in null cases with the Elvis operator: ?:
7.6 Safely casting values without throwing exceptions: as?
7.7 Making promises to the compiler with the non-null assertion operator: !!
7.8 Dealing with nullable expressions: The let function
7.9 Non-null types without immediate initialization: Late-initialized properties
7.10 Extending types without the safe-call operator: Extensions for nullable types
7.11 Nullability of type parameters
7.12 Nullability and Java
7.12.1 Platform types
7.12.2 Inheritance
Summary
8 Basic types, collections, and arrays
8.1 Primitive and other basic types
8.1.1 Representing integers, floating-point numbers, characters, and Booleans with primitive types
8.1.2 Using the full bit range to represent positive numbers: Unsigned number types
8.1.3 Nullable primitive types: Int?, Boolean?, and more
8.1.4 Kotlin makes number conversions explicit
8.1.5 Any and Any?: The root of the Kotlin type hierarchy
8.1.6 The Unit type: Kotlin’s void
8.1.7 The Nothing type: “This function never returns”
8.2 Collections and arrays
8.2.1 Collections of nullable values and nullable collections
8.2.2 Read-only and mutable collections
8.2.3 Kotlin collections and Java collections are deeply related
8.2.4 Collections declared in Java are seen as platform types in Kotlin
8.2.5 Creating arrays of objects and primitive types for interoperability and performance reasons
Summary
Part 2 Embracing Kotlin
9 Operator overloading and other conventions
9.1 Overloading arithmetic operators makes operations for arbitrary classes more convenient
9.1.1 Plus, times, divide, and more: Overloading binary arithmetic operations
9.1.2 Applying an operation and immediately assigning its value: Overloading compound assignment operators
9.1.3 Operators with only one operand: Overloading unary operators
9.2 Overloading comparison operators makes it easy to check relationships between objects
9.2.1 Equality operators: equals (==)
9.2.2 Ordering operators: compareTo (<, >, ⇐, and >=)
9.3 Conventions used for collections and ranges
9.3.1 Accessing elements by index: The get and set conventions
9.3.2 Checking whether an object belongs to a collection: The in convention
9.3.3 Creating ranges from objects: The rangeTo and rangeUntil conventions
9.3.4 Making it possible to loop over your types: The iterator convention
9.4 Making destructuring declarations possible with component functions
9.4.1 Destructuring declarations and loops
9.4.2 Ignoring destructured values using the _ character
9.5 Reusing property accessor logic: Delegated properties
9.5.1 Basic syntax and inner workings of delegated properties
9.5.2 Using delegated properties: Lazy initialization and by lazy()
9.5.3 Implementing your own delegated properties
9.5.4 Delegated properties are translated to hidden properties with custom accessors
9.5.5 Accessing dynamic attributes by delegating to maps
9.5.6 How a real-life framework might use delegated properties
Summary
10 Higher-order functions:Lambdas as parameters and return values
10.1 Declaring functions that return or receive other functions: Higher-order functions
10.1.1 Function types specify the parameter types and return values of a lambda
10.1.2 Calling functions passed as arguments
10.1.3 Java lambdas are automatically converted to Kotlin function types
10.1.4 Parameters with function types can provide defaults or be nullable
10.1.5 Returning functions from functions
10.1.6 Making code more reusable by reducing duplication with lambdas
10.2 Removing the overhead of lambdas with inline functions
10.2.1 Inlining means substituting a function body to each call site
10.2.2 Restrictions on inline functions
10.2.3 Inlining collection operations
10.2.4 Deciding when to declare functions as inline
10.2.5 Using inlined lambdas for resource management with withLock, use, and useLines
10.3 Returning from lambdas: Control flow in higher-order functions
10.3.1 Return statements in lambdas: returning from an enclosing function
10.3.2 Returning from lambdas: Return with a label
10.3.3 Anonymous functions: Local returns by default
Summary
11 Generics
11.1 Creating types with type arguments: Generic type parameters
11.1.1 Functions and properties that work with generic types
11.1.2 Generic classes are declared with the angle bracket syntax
11.1.3 Restricting the type a generic class or function can use: Type parameter constraints
11.1.4 Excluding nullable type arguments by explicitly marking type parameters as non-null
11.2 Generics at run time: Erased and reified type parameters
11.2.1 Limitations to finding type information of a generic class at run time: Type checks and casts
11.2.2 Functions with reified type parameters can refer to actual type arguments at run time
11.2.3 Avoiding java.lang.Class parameters by replacing class references with reified type parameters
11.2.4 Declaring accessors with reified type parameters
11.2.5 Reified type parameters come with restrictions
11.3 Variance describes the subtyping relationship between generic arguments
11.3.1 Variance determines whether it is safe to pass an argument to a function
11.3.2 Understanding the differences between classes, types, and subtypes
11.3.3 Covariance preserves the subtyping relation
11.3.4 Contravariance reverses the subtyping relation
11.3.5 Specifying variance for type occurrences via use-site variance
11.3.6 Star projection: Using the * character to indicate a lack of information about a generic argument
11.3.7 Type aliases
Summary
12 Annotations and reflection
12.1 Declaring and applying annotations
12.1.1 Applying annotations to mark declarations
12.1.2 Specifying the exact declaration an annotation refers to: Annotation targets
12.1.3 Using annotations to customize JSON serialization
12.1.4 Creating your own annotation declarations
12.1.5 Meta-annotations: Controlling how an annotation is processed
12.1.6 Passing classes as annotation parameters to further control behavior
12.1.7 Generic classes as annotation parameters
12.2 Reflection: Introspecting Kotlin objects at run time
12.2.1 The Kotlin reflection API: KClass, KCallable, KFunction, and KProperty
12.2.2 Implementing object serialization using reflection
12.2.3 Customizing serialization with annotations
12.2.4 JSON parsing and object deserialization
12.2.5 The final step of deserialization: callBy() and creating objects using reflection
Summary
13 DSL construction
13.1 From APIs to DSLs: Creating expressive custom code structures
13.1.1 Domain-specific languages
13.1.2 Internal DSLs are seamlessly integrated into the rest of your program
13.1.3 The structure of DSLs
13.1.4 Building HTML with an internal DSL
13.2 Building structured APIs: Lambdas with receivers in DSLs
13.2.1 Lambdas with receivers and extension function types
13.2.2 Using lambdas with receivers in HTML builders
13.2.3 Kotlin builders: Enabling abstraction and reuse
13.3 More flexible block nesting with the invoke convention
13.3.1 The invoke convention: Objects callable as functions
13.3.2 The invoke convention in DSLs: Declaring dependencies in Gradle
13.4 Kotlin DSLs in practice
13.4.1 Chaining infix calls: The should function in test frameworks
13.4.2 Defining extensions on primitive types: Handling dates
13.4.3 Member extension functions: Internal DSL for SQL
Summary
Part 3 Concurrent programming with coroutines and flows
14 Coroutines
14.1 Concurrency vs. parallelism
14.2 Concurrency the Kotlin way: Suspending functions and coroutines
14.3 Comparing threads and coroutines
14.4 Functions that can pause: Suspending functions
14.4.1 Code written with suspending functions looks sequential
14.5 Comparing coroutines to other approaches
14.5.1 Calling a suspending function
14.6 Entering the world of coroutines: Coroutine builders
14.6.1 From regular code into the realm of coroutines: The runBlocking function
14.6.2 Creating start-and-forget coroutines: The launch function
14.6.3 Awaitable computations: The async builder
14.7 Deciding where your code should run: Dispatchers
14.7.1 Choosing a dispatcher
14.7.2 Passing a dispatcher to a coroutine builder
14.7.3 Using withContext to switch the dispatcher within a coroutine
14.7.4 Coroutines and dispatchers aren’t a magical fix for thread-safety concerns
14.8 Coroutines carry additional information in their coroutine context
Summary
15 Structured concurrency
15.1 Coroutine scopes establish structure between coroutines
15.1.1 Creating a coroutine scope: The coroutineScope function
15.1.2 Associating coroutine scopes with components: CoroutineScope
15.1.3 The danger of GlobalScope
15.1.4 Coroutine contexts and structured concurrency
15.2 Cancellation
15.2.1 Triggering cancellation
15.2.2 Invoking cancellation automatically after a time limit has been exceeded
15.2.3 Cancellation cascades through all children
15.2.4 Cancelled coroutines throw CancellationExceptions in special places
15.2.5 Cancellation is cooperative
15.2.6 Checking whether a coroutine has been cancelled
15.2.7 Letting other coroutines play: The yield function
15.2.8 Keep cancellation in mind when acquiring resources
15.2.9 Frameworks can perform cancellation for you
Summary
16 Flows
16.1 Flows model sequential streams of values
16.1.1 Flows allow you to work with elements as they are emitted
16.1.2 Different types of flows in Kotlin
16.2 Cold flows
16.2.1 Creating a cold flow with the flow builder function
16.2.2 Cold flows don’t do any work until collected
16.2.3 Cancelling the collection of a flow
16.2.4 Cold flows under the hood
16.2.5 Concurrent flows with channel flows
16.3 Hot flows
16.3.1 Shared flows broadcast values to subscribers
16.3.2 Keeping track of state in your system: State flow
16.3.3 Comparing state flows and shared flows
16.3.4 Hot, cold, shared, state: When to use which flow
Summary
17 Flow operators
17.1 Manipulating flows with flow operators
17.2 Intermediate operators are applied to an upstream flow and return a downstream flow
17.2.1 Emitting arbitrary values for each upstream element: The transform function
17.2.2 The take operator family can cancel a flow
17.2.3 Hooking into flow phases with onStart, onEach, onCompletion, and onEmpty
17.2.4 Buffering elements for downstream operators and collectors: The buffer operator
17.2.5 Throwing away intermediate values: The conflate operator
17.2.6 Filtering out values on a timeout: The debounce operator
17.2.7 Switching the coroutine context on which a flow is executed: The flowOn operator
17.3 Creating custom intermediate operators
17.4 Terminal operators execute the upstream flow and may compute a value
17.4.1 Frameworks provide custom operators
Summary
18 Error handling and testing
18.1 Handling errors thrown inside coroutines
18.2 Error propagation in Kotlin coroutines
18.2.1 Coroutines cancel all their children when one child fails
18.2.2 Structured concurrency only affects exceptions thrown across coroutine boundaries
18.2.3 Supervisors prevent parents and siblings from being cancelled
18.3 CoroutineExceptionHandler: The last resort for processing exceptions
18.3.1 Differences when using CoroutineExceptionHandler with launch or async
18.4 Handling errors in flows
18.4.1 Processing upstream exceptions with the catch operator
18.4.2 Retry the collection of a flow if predicate is true: The retry operator
18.5 Testing coroutines and flows
18.5.1 Making tests using coroutines fast: Virtual time and the test dispatcher
18.5.2 Testing flows with Turbine
Summary
appendix A. Building Kotlin projects
Building Kotlin code with Gradle
Building projects that use annotation processing
Building Kotlin projects with Maven
appendix B. Documenting Kotlin code
Writing Kotlin documentation comments
Generating API documentation
appendix C. The Kotlin ecosystem
Testing
Code coverage
Benchmarking
Documentation
Dependency injection
Networked applications: Servers and clients
Serialization
Database access
Concurrent programming
User interface development
index

Kotlin in Action, Second Edition takes you from language basics to building production-quality applications that take advantage of Kotlin’s unique features. Discover how the language handles everything from statements and functions to classes and types, and the unique features that make Kotlin programming so seamless.

In Kotlin in Action, Second Edition you will learn:

  • Kotlin statements and functions, and classes and types

  • Functional programming on the JVM

  • The Kotlin standard library and out-of-the-box features

  • Writing clean and idiomatic code

  • Combining Kotlin and Java

  • Improve code reliability with null safety

  • Domain-specific languages

  • Kotlin coroutines and flows

  • Mastering the kotlinx.coroutines library

Kotlin in Action, Second Edition is a complete guide to the Kotlin language written especially for readers familiar with Java or another OO language. Its authors—all core Kotlin language developers and Kotlin team members—share their unique insights, along with practical techniques and hands-on examples. This new second edition is fully updated to include the latest innovations, and it adds new chapters dedicated to coroutines, flows, and concurrency.

About the technology

Kotlin is a low-hassle, high-productivity programming language flexible enough to handle any web, mobile, cloud, and enterprise application. Java developers will appreciate the simple syntax, intuitive type system, excellent tooling, and support for functional-style programming. Plus, since Kotlin runs on the JVM, it integrates seamlessly with existing Java code, libraries, and frameworks, including Spring and Android.

About the book

Kotlin in Action, Second Edition teaches you Kotlin techniques you can use for almost any type of application, from enterprise services to Android apps. The authors are all members of the Kotlin team, so you can trust that even the gnarly details are dead accurate. You’ll start with Kotlin fundamentals, learning how the language handles everything from statements and functions to classes and types, and about its unique features that make Kotlin programming so seamless.
As you progress through this masterful book, you’ll get hands-on with the Kotlin standard library, functional programming in Kotlin, and advanced features such as generics and reflection. And this updated second edition now covers coroutines and structured concurrency to help you create efficient high-performance applications.

What's inside

  • Guidance from members of the Kotlin team

  • Domain-specific languages

  • Kotlin coroutines and flows

About the reader

For readers familiar with Java or another OO language.
 


Похожее:

Список отзывов:

Нет отзывов к книге.