+353-1-416-8900REST OF WORLD
+44-20-3973-8888REST OF WORLD
1-917-300-0470EAST COAST U.S
1-800-526-8630U.S. (TOLL FREE)

Programming Kotlin Applications. Building Mobile and Server-Side Applications with Kotlin. Edition No. 1

  • Book

  • 384 Pages
  • February 2021
  • John Wiley and Sons Ltd
  • ID: 5186059
Learn to program with Kotlin, one of the fastest-growing programming languages available today

Programming Kotlin Applications: Building Mobile and Server-Side Applications with Kotlin drops readers into the fast lane for learning to develop with the Kotlin programming language. Authored by accomplished cloud consultant and technology professional Brett McLaughlin, Programming Kotlin Applications provides readers with the pragmatic and practical advice they need to build their very first Kotlin applications.

Designed to give readers a thorough understanding of Kotlin that goes beyond mere mobile programming, this book will help you:
  • Learn how to develop your first Kotlin project
  • Understand how Kotlin securely protects and stores information
  • Advocate for using Kotlin in your own professional and personal environments
  • Understand Kotlin's goals and how to use it as its best
  • Know when to avoid using Kotlin
Programming Kotlin Applications is written in a highly approachable and accessible way without the fluff and unrealistic samples that characterize some of its competitor guides. Perfect for developers familiar with another object-oriented programming language like Java or Ruby, or for people who want to advance their skillset in the Kotlin environment, this book is an indispensable addition to any programmer’s library.

Table of Contents

Introduction xxv

Chapter 1: Objects All The Way Down 1

Kotlin: A New Programming Language 1

What is Kotlin? 2

What Does Kotlin Add to Java? 3

Kotlin is Object-Oriented 3

Interlude: Set Up Your Kotlin Environment 4

Install Kotlin (and an IDE) 4

Install IntelliJ 5

Create Your Kotlin Program 8

Compile and Run Your Kotlin Program 9

Fix Any Errors as They Appear 10

Install Kotlin (and Use the Command Line) 10

Command-Line Kotlin on Windows 10

Command-Line Kotlin on Mac OS X 11

Command-Line Kotlin on UNIX-Based Systems 12

Verify Your Command-Line Installation 12

Creating Useful Objects 13

Pass In Values to an Object Using Its Constructor 13

Print an Object with toString() 14

Terminology Update: Functions and Methods 15

Print an Object (and Do It with Shorthand) 15

Override the toString() Method 16

All Data is Not a Property Value 17

Initialize an Object and Change a Variable 19

Initialize a Class with a Block 19

Kotlin Auto-Generates Getters and Setters 20

Terminology Update: Getters, Setters, Mutators, Accessors 20

Constants Can’t Change (Sort of) 21

Chapter 2: It’s Hard To Break Kotlin 25

Upgrade Your Kotlin Class Game 25

Name a File According to Its Class 26

Organize Your Classes with Packages 27

Put Person in a Package 28

Classes: The Ultimate Type in Kotlin 31

Kotlin Has a Large Number of Types 31

Numbers in Kotlin 31

Letters and Things 32

Truth or Fiction 33

Types Aren’t Interchangeable (Part 1) 33

You Must Initialize Your Properties 34

Types Aren’t Interchangeable (Part 2) 35

You Can Explicitly Tell Kotlin What Type to Use 36

Try to Anticipate How Types Will Be Used 37

It’s Easy to Break Kotlin (Sort of) 37

Overriding Property Accessors and Mutators 37

Custom-Set Properties Can’t Be in a Primary Constructor 38

Move Properties Out of Your Primary Constructors 38

Initialize Properties Immediately 39

Try to Avoid Overusing Names 41

Override Mutators for Certain Properties 41

Classes Can Have Custom Behavior 43

Define a Custom Method on Your Class 43

Every Property Must Be Initialized 44

Assign an Uninitialized Property a Dummy Value 45

Tell Kotlin You’ll Initialize a Property Later 45

Assign Your Property the Return Value from a Function 46

Sometimes You Don’t Need a Property! 47

TYPE SAFETY CHANGES EVERYTHING 49

Writing Code is Rarely Linear 49

Chapter 3: Kotlin is Extremely Classy 51

Objects, Classes, and Kotlin 51

All Classes Need an equals(x) Method 52

Equals(x) is Used to Compare Two Objects 52

Override equals(x) to Make It Meaningful 54

Every Object is a Particular Type 56

A Brief Introduction to Null 58

Every Object Instance Needs a Unique hashCode() 59

All Classes Inherit from Any 59

Always Override hashCode() and equals(x) 61

Default Hash Codes Are Based on Memory Location 63

Use Hash Codes to Come Up with Hash Codes 63

Searching (and Other Things) Depend on Useful and Fast equals(x) and hashCode() 64

Multiple Properties to Differentiate Them in hashCode() 65

Use == over equals(x) for Speed 66

A Quick Speed Check on hashCode() 66

Basic Class Methods Are Really Important 67

Chapter 4: Inheritance Matters 69

Good Classes Are Not Always Complex Classes 69

Keep It Simple, Stupid 70

Keep It Flexible, Stupid 71

Classes Can Define Default Values for Properties 73

Constructors Can Accept Default Values 74

Kotlin Expects Arguments in Order 74

Specify Arguments by Name 74

Change the Order of Arguments (If You Need) 75

Secondary Constructors Provide Additional Construction Options 76

Secondary Constructors Come Second 76

Secondary Constructors Can Assign Property Values 77

You Can Assign null to a Property . . . Sometimes 79

null Properties Can Cause Problems 81

Handle Dependent Values with Custom Mutators 82

Set Dependent Values in a Custom Mutator 82

All Property Assignments Use the Property’s Mutator 83

Nullable Values Can Be Set to null! 84

Limit Access to Dependent Values 86

When Possible, Calculate Dependent Values 87

You Can Avoid Parentheses with a Read-Only Property 88

Need Specifics? Consider a Subclass 91

Any is the Base Class for Everything in Kotlin 91

{ . . . } Is Shorthand for Collapsed Code 93

A Class Must Be Open for Subclassing 94

Terminology: Subclass, Inherit, Base Class, and More 95

A Subclass Must Follow Its Superclass’s Rules 96

A Subclass Gets Behavior from All of Its Superclasses 96

Your Subclass Should Be Different Than Your Superclass 97

Subclass Constructors Often Add Arguments 97

Don’t Make Mutable What Isn’t Mutable 98

Sometimes Objects Don’t Exactly Map to the Real World 99

Generally, Objects Should Map to the Real World 99

Chapter 5: Lists and Sets and Maps, Oh My! 101

Lists Are Just a Collection of Things 101

Kotlin Lists: One Type of Collection 101

Collection is a Factory for Collection Objects 102

Collection is Automatically Available to Your Code 104

Mutating a Mutable List 105

Getting Properties from a Mutable List 105

Lists (and Collections) Can Be Typed 106

Give Your Lists Types 107

Iterate over Your Lists 108

Kotlin Tries to Figure Out What You Mean 111

Lists Are Ordered and Can Repeat 111

Order Gives You Ordered Access 112

Lists Can Contain Duplicate Items 112

Sets: Unordered but Unique 113

In Sets, Ordering is Not Guaranteed 114

When Does Order Matter? 115

Sort Lists (and Sets) on the Fly 115

Sets: No Duplicates, No Matter What 116

Sets “Swallow Up” Duplicates 116

Sets Use equals(x) to Determine Existing Membership 116

Using a Set? Check equals(x) 119

Iterators Aren’t (Always) Mutable 119

Maps: When a Single Value Isn’t Enough 119

Maps Are Created by Factories 120

Use Keys to Find Values 120

How Do You Want Your Value? 121

Filter a Collection by . . . Anything 121

Filter Based on a Certain Criterion 122

Filter Has a Number of Useful Variations 123

Collections: For Primitive and Custom Types 123

Add a Collection to Person 124

Allow Collections to Be Added to Collection Properties 126

Sets and MutableSets Aren’t the Same 127

Collection Properties Are Just Collections 128

Chapter 6: The Future (In Kotlin) is Generic 129

Generics Allow Deferring of a Type 129

Collections Are Generic 129

Parameterized Types Are Available Throughout a Class 130

Generic: What Exactly Does It Refer To? 131

Generics Try to Infer a Type When Possible 132

Kotlin Looks for Matching Types 132

Kotlin Looks for the Narrowest Type 132

Sometimes Type Inference is Wrong 133

Don’t Assume You Know Object Intent 133

Kotlin Doesn’t Tell You the Generic Type 134

Just Tell Kotlin What You Want! 134

Covariance: A Study in Types and Assignment 134

What about Generic Types? 135

Some Languages Take Extra Work to Be Covariant 137

Kotlin Actually Takes Extra Work to Be Covariant, Too 137

Sometimes You Have to Make Explicit What is Obvious 137

Covariant Types Limit the Input Type as Well as the Output Type 137

Covariance is Really about Making Inheritance Work the Way You Expect 138

Contravariance: Building Consumers from Generic Types 138

Contravariance: Limiting What Comes Out Rather Than What Comes In 139

Contravariance Works from a Base Class Down to a Subclass 141

Contravariant Classes Can’t Return a Generic Type 141

Does Any of This Really Matter? 142

Unsafevariance: Learning The Rules, then Breaking Them 142

Typeprojection Lets You Deal with Base Classes 143

Variance Can Affect Functions, Not Just Classes 143

Type Projection Tells Kotlin to Allow Subclasses as Input for a Base Class 144

Producers Can’t Consume and Consumers Can’t Produce 145

Variance Can’t Solve Every Problem 145

Chapter 7: Flying Through Control Structures 147

Control Structures Are the Bread and Butter of Programming 147

If and Else: The Great Decision Point 148

!! Ensures Non-Nullable Values 148

Control Structures Affect the Flow of Your Code 149

if and else Follow a Basic Structure 150

Expressions and if Statements 151

Use the Results of an if Statement Directly 152

Kotlin Has No Ternary Operator 153

A Block Evaluates to the Last Statement in That Block 153

if Statements That Are Assigned Must Have else Blocks 154

When is Kotlin’s Version of Switch 154

Each Comparison or Condition is a Code Block 155

Handle Everything Else with an else Block 156

Each Branch Can Support a Range 157

Each Branch Usually Has a Partial Expression 158

Branch Conditions Are Checked Sequentially 159

Branch Conditions Are Just Expressions 159

When Can Be Evaluated as a Statement, Too 160

For is for Looping 161

For in Kotlin Requires an Iterator 162

You Do Less, Kotlin Does More 163

For Has Requirements for Iteration 163

You Can Grab Indices Instead of Objects with for 164

Use While to Execute until a Condition is False 167

While is All about a Boolean Condition 167

A Wrinkle in while: Multiple Operators, One Variable 168

Combine Control Structures for More Interesting Solutions 169

Do . . . While Always Runs Once 170

Every do . . . while Loop Can Be Written as a while Loop 170

If Something Must Happen, Use do . . . while 171

do . . . while Can Be a Performance Consideration 175

Get Out of a Loop Immediately with Break 176

Break Skips What’s Left in a Loop 176

You Can Use a Label with break 177

Go to the Next Iteration Immediately with Continue 178

Continue Works with Labels as Well 179

If versus continue: Mostly Style over Substance 179

Return Returns 180

Chapter 8: Data Classes 183

Classes in the Real World Are Varied but Well Explored 183

Many Classes Share Common Characteristics 183

Common Characteristics Result in Common Usage 185

A Data Class Takes the Work Out of a Class Focused on Data 185

Data Classes Handle the Basics of Data for You 185

The Basics of Data Includes hashCode() and equals(x) 186

Destructuring Data through Declarations 188

Grab the Property Values from a Class Instance 188

Destructuring Declarations Aren’t Particularly Clever 189

Kotlin is Using componentN() Methods to Make Declarations Work 190

You Can Add componentN() Methods to Any Class 191

If You Can Use a Data Class, You Should 192

You Can “Copy” an Object or Make a Copy Of an Object 192

Using = Doesn’t Actually Make a Copy 192

If You Want a Real Copy, Use copy() 193

Data Classes Require Several Things from You 194

Data Classes Require Parameters and val or var 194

Data Classes Cannot Be Abstract, Open, Sealed, or Inner 195

Data Classes Add Special Behavior to Generated Code 195

You Can Override Compiler-Generated Versions of Many Standard Methods 196

Supertype Class Functions Take Precedence 196

Data Classes Only Generate Code for Constructor Parameters 197

Only Constructor Parameters Are Used in equals() 199

Data Classes Are Best Left Alone 200

Chapter 9: Enums and Sealed, More Specialty Classes 203

Strings Are Terrible as Static Type Representations 203

Strings Are Terrible Type Representations 204

Capitalization Creates Comparison Problems 205

This Problem Occurs All the Time 206

String Constants Can Help . . . Some 206

Companion Objects Are Single Instance 207

Constants Must Be Singular 208

Companion Objects Are Singletons 209

Companion Objects Are Still Objects 210

You Can Use Companion Objects without Their Names 211

Using a Companion Object’s Name is Optional 211

Using a Companion Object’s Name is Stylistic 213

Companion Object Names Are Hard 214

You Can Skip the Companion Object Name Altogether 215

Enums Define Constants and Provide Type Safety 216

Enums Classes Provide Type-Safe Values 216

Enums Classes Are Still Classes 218

Enums Give You the Name and Position of Constants 219

Each Constant in an enum is an Object 219

Each Constant Can Override Class-Level Behavior 220

Sealed Classes Are Type-Safe Class Hierarchies 221

Enums and Class Hierarchies Work for Shared Behavior 222

Sealed Classes Address Fixed Options and Non-Shared Behavior 222

Sealed Classes Don’t Have Shared Behavior 223

Sealed Classes Have a Fixed Number of Subclasses 224

Subclasses of a Sealed Class Don’t Always Define Behavior 225

when Requires All Sealed Subclasses to Be Handled 225

when Expressions Must Be Exhaustive for Sealed Classes 226

else Clauses Usually Don’t Work for Sealed Classes 228

else Clauses Hide Unimplemented Subclass Behavior 229

Chapter 10: Functions and Functions and Functions 233

Revisiting the Syntax of a Function 233

Functions Follow a Basic Formula 233

Function Arguments Also Have a Pattern 235

Default Values in Constructors Are Inherited 237

Default Values in Functions Are Inherited 238

Default Values in Functions Cannot Be Overridden 239

Default Values Can Affect Calling Functions 239

Calling Functions Using Named Arguments is Flexible 241

Function Arguments Can’t Be Null Unless You Say So 241

Functions Follow Flexible Rules 243

Functions Actually Return Unit by Default 243

Functions Can Be Single Expressions 244

Single-Expression Functions Don’t Have Curly Braces 245

Single-Expression Functions Don’t Use the return Keyword 246

Single-Expression Functions Can Infer a Return Type 246

Type Widening Results in the Widest Type Being Returned 248

Functions Can Take Variable Numbers of Arguments 249

A vararg Argument Can Be Treated Like an Array 251

Functions in Kotlin have Scope 251

Local Functions Are Functions Inside Functions 252

Member Functions Are Defined in a Class 252

Extension Functions Extend Existing Behavior without Inheritance 253

Extend an Existing Closed Class Using Dot Notation 253

this Gives You Access to the Extension Class 255

Function Literals: Lambdas and Anonymous Functions 257

Anonymous Functions Don’t Have Names 257

You Can Assign a Function to a Variable 258

Executable Code Makes for an “Executable” Variable 259

Higher-Order Functions Accept Functions as Arguments 260

The Result of a Function is Not a Function 260

Function Notation Focuses on Input and Output 261

You Can Define a Function Inline 263

Lambda Expressions Are Functions with Less Syntax 264

You Can Omit Parameters Altogether 266

Lambda Expressions Use it for Single Parameters 266

It Makes Lambdas Work More Smoothly 267

Lambda Expressions Return the Last Execution Result 267

Trailing Functions as Arguments to Other Functions 268

Lots of Functions, Lots of Room for Problems 268

Chapter 11: Speaking Idiomatic Kotlin 271

Scope Functions Provide Context to Code 271

Use Let to Provide Immediate Access to an Instance 272

let Gives You it to Access an Instance 273

The Scoped Code Blocks Are Actually Lambdas 274

let and Other Scope functions Are Largely about Convenience 275

You Can Chain Scoped Function Calls 275

An Outer it “Hides” an Inner it 276

Chaining Scope Functions and Nesting Scope Functions Are Not the Same 277

Nesting Scope Functions Requires Care in Naming 277

Chaining Scope Functions is Simpler and Cleaner 278

Prefer Chaining over Nesting 279

Many Chained Functions Start with a Nested Function 280

You Can Scope Functions to Non-Null Results 280

Accepting null Values Isn’t a Great Idea 282

Scope Functions Give You Null Options 282

Scope Functions Work on Other Functions . . . In Very Particular Ways 284

With is a Scope Function for Processing an Instance 287

with Uses this as Its Object Reference 287

A this Reference is Always Available 288

with Returns the Result of the Lambda 289

Run is a Code Runner and Scope Function 289

Choosing a Scope Function is a Matter of Style and Preference 290

run Doesn’t Have to Operate on an Object Instance 291

Apply Has a Context Object but No Return Value 292

apply Operates Upon an Instance 292

apply Returns the Context Object, Not the Lambda Result 293

?: is Kotlin’s Elvis Operator 293

Also Gives You an Instance . . . but Operates on the Instance First 294

also is Just Another Scope Function 295

also Executes before Assignment 296

Scope Functions Summary 298

Chapter 12: Inheritance, One More Time, With Feeling 303

Abstract Classes Require a Later Implementation 303

Abstract Classes Cannot Be Instantiated 304

Abstract Classes Define a Contract with Subclasses 306

Abstract Classes Can Define Concrete Properties and Functions 308

Subclasses Fulfill the Contract Written by an Abstract Class 310

Subclasses Should Vary Behavior 310

The Contract Allows for Uniform Treatment of Subclasses 311

Interfaces Define Behavior but Have No Body 313

Interfaces and Abstract Classes Are Similar 315

Interfaces Cannot Maintain State 316

A Class’s State is the Values of Its Properties 317

An Interface Can Have Fixed Values 317

Interfaces Can Define Function Bodies 318

Interfaces Allow Multiple Forms of Implementation 319

A Class Can Implement Multiple Interfaces 320

Interface Property Names Can Get Confusing 321

Interfaces Can Decorate a Class 321

Delegation Offers Another Option for Extending Behavior 322

Abstract Classes Move from Generic to Specific 322

More Specificity Means More Inheritance 324

Delegating to a Property 326

Delegation Occurs at Instantiation 329

Inheritance Requires Forethought and Afterthought 330

Chapter 13: Kotlin: The Next Step 331

Programming Kotlin for Android 331

Kotlin for Android is Still Just Kotlin 331

Move from Concept to Example 333

Kotlin and Java Are Great Companions 333

Your IDE is a Key Component 333

Kotlin is Compiled to Bytecode for the Java Virtual Machine 335

Gradle Gives You Project Build Capabilities 335

When Kotlin Questions Still Exist 335

Use the Internet to Supplement Your Own Needs and Learning Style 336

Now What? 337

Index 339

Authors

Brett McLaughlin