Jake Wharton Possible Futures with Kotlin

Kotlin?

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName: String = "Jake" 
 val lastName: String? = null

val firstName = "Jake" 
 val lastName: String? = null

class User { 


public String getName() { 


// ... 


} 


public void setName(String name) { 


// ... 


} 
 }

// ^^^ Java

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is "

  • user. name )

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is "

  • user. name ) X

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is ${ user. name } " ) X

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is $ user " ) X

class User { 


public String getName() { 


// ... 


} X 


public void setName(String name) { 


// ... 


} Y 
 } Z

// ^^^ Java vvv Kotlin

val user = User() 
 println ( "Name is $ user " ) X

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "

  • user.getName());

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "

  • user.getName());

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "

  • user.getName());

user.setName( "Jane" );

class User { 


var name

"Jake" 
 }

// ^^^ Kotlin vvv Java User user = new User(); System. out .println( "Name is "

  • user.getName());

user.setName( "Jane" );

val user = User()

val user = User() 
 user = User()

val user = User() 
 user = User() 



 var currentUser = User() 
 currentUser = User()

fun Date.isTuesday(): Boolean { 


return day

2 
 }

fun Date.isTuesday(): Boolean { 


return day

2 
 }

val epoch = Date( 1970 , 0 , 0 ) 
 if (epoch. isTuesday ()) { 


println ( "The epoch was a Tuesday." ) 
 } else { 


println ( "The epoch was not a Tuesday." ) 
 }

fun Date.isTuesday(): Boolean { 


return day

2 
 }

val epoch = Date( 1970 , 0 , 0 ) 
 if (epoch. isTuesday ()) { 


println ( "The epoch was a Tuesday." ) 
 } else { 


println ( "The epoch was not a Tuesday." ) 
 }

fun Date.isTuesday(): Boolean { 


return day

2 
 }

val epoch = Date( 1970 , 0 , 0 ) 
 if (epoch. isTuesday ()) { 


println ( "The epoch was a Tuesday." ) 
 } else { 


println ( "The epoch was not a Tuesday." ) 
 } // ^^^ Kotlin vvv Java DateKt. isTuesday (date)

val executor = Executors.newSingleThreadExecutor(); 
 executor. execute { B println ( "Background thread!" ) } X

val executor = Executors.newSingleThreadExecutor();

val foo = Foo() 
 executor. execute (foo::printIt)

class Foo {

fun printIt() { B

println(

"Background thread!" ) } X

}

val executor = Executors.newSingleThreadExecutor();

val foo = Foo() 
 executor. execute (foo::printIt)

class Foo {

fun printIt() { B

println(

"Background thread!" ) } X

}

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter ( { item -> item % 2 != 0 } ) B

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter ( { item -> item % 2 != 0 } ) B

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter ( { it % 2 != 0 } ) B

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter () B { it % 2 != 0 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter { it % 2 != 0 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val oddList = items. filter { it % 2 != 0 }

val oddSet = items. filterTo(mutableListOf()) { it % 2 != 0 }

fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter { it % 2 != 0 }

inline fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T { 


// ... 
 } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter { it % 2 != 0 }

inline fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T {

val destination = mutableListOf < T

()

for (item in this ) {

if (predicate(item)) destination.add(item) } B

return destination } A

val items = listOf ( 1 , 2 , 3 ) val odds = items. filter { it % 2 != 0 } val destination = mutableListOf <

() for (item in

) {

if ( item ) destination.add(item) } G

destination

inline fun < T

List< T .filter(predicate: ( T ) -> Boolean): List< T {

val destination = mutableListOf < T

()

for (item in this ) {

if (predicate(item)) destination.add(item) } B

return destination } A

val items = listOf ( 1 , 2 , 3 ) val destination = mutableListOf <Int>() for (item in items ) {

if (item % 2 != 0 ) destination.add(item) } G

val odds = destination

filter

it

class User { D 


val name

"Jake" 
 } A

class User(name: String) { D 


val name = name 
 } A 


    "

Jake"

class User( val

name : String) { 
 } A

class User( val

name : String)

class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

Hello, User@3a71f4dd !

data class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

Hello, User@3a71f4dd !

@3a71f4dd data class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

Hello, User(name=Jake) !

data class User( val

name : String)

val jake = User( "Jake" ) println ( "Hello, $ jake !" )

Hello, User(name=Jake) !

class UserPersisence(db: SqlDatabase) {

private val deleteByName

= db.createStatement( "DELETE FROM user WHERE name = ?" )

fun delete(name: String) {

deleteByName .bind( 1 , name)

deleteByName .execute() } }

class UserPersisence(db: SqlDatabase) {

private val deleteByName

= db.createStatement( "DELETE FROM user WHERE name = ?" )

fun delete(name: String) {

deleteByName .bind( 1 , name)

deleteByName .execute() } B

} A

class UserPersisence(db: SqlDatabase) {

private val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" )

} C

fun delete(name: String) {

deleteByName .bind( 1 , name)

deleteByName .execute() } B

} A

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C var name by Delegates.observable( "Jane" ) { prop, old, new ->

println ( "Name changed from $ old to $ new " ) }

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C var name by Delegates.observable( "Jane" ) { prop, old, new ->

println ( "Name changed from $ old to $ new " ) }

var address by Delegates.notNull<String>()

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C var name by Delegates.observable( "Jane" ) { prop, old, new ->

println ( "Name changed from $ old to $ new " ) }

var address by Delegates.notNull<String>() val nameView by bindView <TextView>(R. id . name )

val deleteByName by lazy {

db.createStatement( "DELETE FROM user WHERE name = ?" ) } C var name by Delegates.observable( "Jane" ) { prop, old, new ->

println ( "Name changed from $ old to $ new " ) }

var address by Delegates.notNull<String>() val nameView by bindView <TextView>(R. id . name )

fun main( vararg args: String) = runBlocking<Unit> {

val jobs = List ( 100_000 ) {

launch(CommonPool) {

delay( 1000L )

print ( "." )

} }

jobs.forEach { it.join() } }

X
O
X

X X O O O
X

iOS Web Server / API Android

package xo; public enum Mark {

X , O ; }

package xo; import java.util.Arrays; public final class Board {

private static final int SIZE

3 ;

private final Mark[][] cells ;

public Board() {

this . cells

new Mark[ 3 ][ 3 ]; }

// TODO mutator methods...

@Override public boolean equals(Object o) {

if ( this == o) return true ;

if (!(o instanceof Board)) return false ; Board other = (Board) o;

return Arrays. deepEquals ( cells , other. cells ); }

@Override public int hashCode() {

return Arrays. deepHashCode ( cells ); }

package xo; import static java.util.Objects. requireNonNull ; public final class Player {

public final String name ;

public final Mark mark ;

public Player(String name, Mark mark) {

this . name

requireNonNull (name, "name == null" );

this . mark

requireNonNull (mark, "mark == null" ); }

@Override public boolean equals(Object o) {

if ( this == o) return true ;

if (!(o instanceof Player)) return false ; Player other = (Player) o;

return name .equals(other. name ) && mark == other. mark ; }

@Override public int hashCode() {

return 31 * name .hashCode() + mark .hashCode(); }

@Override public String toString() {

package xo; public enum State {

PLAYER_1_MOVE ,

PLAYER_2_MOVE ,

PLAYER_1_WIN ,

PLAYER_2_WIN ,

DRAW , }

package xo; import static java.util.Objects. requireNonNull ; public final class Game {

private final Board board ;

private final Player player1 ;

private final Player player2 ;

private State state = State. PLAYER_1_MOVE ;

public Game(Board board, Player player1, Player player2) {

this . board

requireNonNull (board, "board == null" );

this . player1

requireNonNull (player1, "player1 == null" );

this . player2

requireNonNull (player2, "player2 == null" ); }

// TODO mutator methods...

@Override public boolean equals(Object o) {

if ( this == o) return true ;

if (!(o instanceof Game)) return false ; Game other = (Game) o;

return board .equals(other. board ) && player1 .equals(other. player1 ) && player2 .equals(other. player2 )

Game Board Mark State Player

public final class Player {

public final String name ;

public final Mark mark ;

public Player(String name, Mark mark) {

this . name

requireNonNull (name, "name == null" );

this . mark

requireNonNull (mark, "mark == null" ); } A

@Override public boolean equals(Object o) {

if ( this == o) return true ;

if (!(o instanceof Player)) return false ; Player other = (Player) o;

return name .equals(other. name ) && mark == other. mark ; } B

@Override public int hashCode() {

return 31 * name .hashCode() + mark .hashCode(); } C

@Override public String toString() {

return "Player{name='" + name + ", mark=" + mark + '}' ; } D

} E

data class Player( val name : String, val mark : Mark) public final { public final ; public final ; public Player(String name, Mark mark) { this . name = requireNonNull (name, "name == null" ); this . mark = requireNonNull (mark, "mark == null" ); } A @Override public boolean equals(Object o) { if ( this == o) return true ; if (!(o instanceof Player)) return false ; Player other = (Player) o; return name .equals(other. name ) && mark == other. mark ; } B @Override public int hashCode() { return 31 * name .hashCode() + mark .hashCode(); } C @Override public String toString() { return "Player{name='" + name + ", mark=" + mark + '}' ; } D } E

Game Mark State Board Player

State Board Game Mark Player

Game Mark State Board *.java *.kt Player

*.kt Game Mark State *.java

kotlinc *.kt Game Mark State *.java

*.kt Game Mark State *.java kotlinc

javac *.kt Game Mark State *.java kotlinc

javac *.kt Game Mark State *.java kotlinc

kotlinc javac *.kt Game Mark State *.java

kotlinc javac *.kt Game Mark State *.java

iOS Web Server / API Android

iOS Android Web Server / API

iOS Android View Models Web Server / API

iOS Android View Models Presenters Web Server / API

iOS Web Android View Models Presenters Server / API

iOS Web Android View Models Presenters Client Backend Server / API

iOS Web Server / API Android View Models Presenters Client Backend

iOS Web Server / API Android View Models Presenters Client Backend Business Logic

iOS Web Server / API Android View Models Presenters Client Backend Business Logic Models

iOS Android View Models Web Server / API Presenters Client Backend Business Logic Models

data class NewGameUi Model(

val winTotal : Long,

val lossTotal : Long )

data class NewGameUi Model(

val winTotal : Long,

val lossTotal : Long )

data class GameUi Model(

val game : Game )

iOS Android View Models Web Server / API Presenters Client Backend Business Logic Models

iOS Android View Models Web Server / API Presenters Client Backend Business Logic Models

iOS Android View Models Presenters Web Server / API Client Backend Business Logic Models

class NewGamePresenter { C

fun model(): NewGameUi Model { } B

} A

class NewGamePresenter( private val gameStore : GameStore) { C

fun model(): NewGameUi Model { } B

} A

class NewGamePresenter( private val gameStore : GameStore) { C

fun model(): NewGameUi Model {

val totals = gameStore .totals()

return NewGameUiModel(totals. wins , totals. losses ) } B

} A

class GamePresenter

{ D

fun model(): GameUiModel { C

} B

} A

class GamePresenter( private val gameId : Long) { D

fun model(): GameUiModel { C

} B

} A

class GamePresenter(

private val gameId : Long,

private val gameStore : GameStore ) { D

fun model(): GameUiModel { C

} B

} A

class GamePresenter(

private val gameId : Long,

private val gameStore : GameStore ) { D

fun models(): Observable<GameUiModel> { C

} B

} A

class GamePresenter(

private val gameId : Long,

private val gameStore : GameStore ) { D

fun move(row: Int, col: Int ) Z { C

} G

fun models(): Observable<GameUiModel> { C

} B

} A

class GamePresenter(

private val gameId : Long,

private val gameStore : GameStore ) { D

fun models(events: Observable<UiEvent>): Observable<GameUiModel> { C

} B

sealed class UiEvent {

data class Move( val

row : Int, val

col : Int): UiEvent() // ... }

} A fun move( ) Z { C } G

iOS Android View Models Presenters Web Server / API Client Backend Business Logic Models

iOS Android View Models Presenters Web Server / API Client Backend Business Logic Models

iOS Web Android View Models Presenters Server / API Client Backend Business Logic Models

iOS Web Android View Models Presenters Server / API Client Backend Business Logic Models

iOS Web Android View Models Presenters Client Backend Server / API Business Logic Models

interface GameStore {

} A

interface GameStore {

fun totals(): Single<Totals>

data class Totals( val wins : Long, val losses : Long) } A

interface GameStore {

fun totals(): Single<Totals>

fun game(id: Long): Observable<Game>

data class Totals( val wins : Long, val losses : Long) } A

interface GameStore {

fun totals(): Single<Totals>

fun game(id: Long): Observable<Game>

fun move(id: Long, row: Int, col: Int): Completable

data class Totals( val wins : Long, val losses : Long) } A

iOS Web Android View Models Presenters Client Backend Server / API Business Logic Models

iOS Web Android View Models Presenters Client Backend Server / API Business Logic Models

Android iOS Web Client Backend iOS Web Server / API Android View Models Presenters Business Logic Models

class SqliteGameStore( private val

db : SQLiteDatabase) : GameStore {

override fun totals() = TODO ()

override fun game(id: Long) = TODO ()

override fun move(id: Long, row: Int, col: Int) = TODO ()

}

class IosGameStore( private val

db : CoreDataGameStore) : GameStore {

override fun totals() = TODO ()

override fun game(id: Long) = TODO ()

override fun move(id: Long, row: Int, col: Int) = TODO ()

}

class IosGameStore(

) : GameStore {

override fun totals() = TODO ()

override fun game(id: Long) = TODO ()

override fun move(id: Long, row: Int, col: Int) = TODO ()

}

private val

db : CoreDataGameStore

class IosGameStore(

) : GameStore {

override fun totals() = TODO ()

override fun game(id: Long) = TODO ()

override fun move(id: Long, row: Int, col: Int) = TODO ()

}

private val

db : CoreDataGameStore // tictactoe.def headers = game_store.h

class StorageGameStore( private val

store : Storage) : GameStore {

override fun totals() = TODO ()

override fun game(id: Long) = TODO ()

override fun move(id: Long, row: Int, col: Int) = TODO ()

} A

import org.w3c.dom.Storage class StorageGameStore(

    )

: GameStore {

override fun totals() = TODO ()

override fun game(id: Long) = TODO ()

override fun move(id: Long, row: Int, col: Int) = TODO ()

} A

              private val

store : Storage

Android iOS Web Client Backend iOS Web Server / API

Android View Models Presenters Business Logic Models

Android iOS Web iOS Web Android View Models Presenters Client Backend Server / API Business Logic Models

Android iOS Web iOS Web Server / API Android View Models Presenters Client Backend Business Logic Models

Android iOS Web iOS Web Server / API Android View Models Presenters Client Backend Business Logic Models

object TicTacToeLogic {

fun validateMove(

game: Game, player: Player, row: Int, col: Int): Boolean {

when (game. state ) { State. PLAYER_1_MOVE -> require (game. player1 == player)

State. PLAYER_2_MOVE -> require (game. player2 == player)

else -> error ( "Game is over" ) }

return game. board [row][col] == null

}

fun nextState(game: Game): State { findWinner(game. board )?. let {

return if (game. player1 . mark

it ) State. PLAYER_1_WIN

else State. PLAYER_2_WIN

}

if (game. board . isComplete ()) {

return State. DRAW

}

return if (game. state == State. PLAYER_1_MOVE ) State. PLAYER_2_MOVE

else State. PLAYER_1_MOVE

}

fun findWinner(board: Board): Mark? = TODO ()

fun Board.isComplete(): Boolean = TODO ()

}

Android iOS Web iOS Web Server / API Android View Models Presenters Client Backend Business Logic Models

Android iOS Web iOS Web Server / API Android View Models Presenters Client Backend Business Logic Models

Android iOS Web iOS Web Server / API Android View Models Presenters Client Backend Business Logic Models

iOS Web Server / API Android Android iOS Web View Models Presenters Client Backend Business Logic Models

class GameView(context: Context, attrs: AttributeSet)

: Consumer<GamePresenter.UiModel> {

fun accept(model: GamePresenter.UiModel) {

// TODO bind to view...

} }

iOS ???

function update(model) {

// TODO bind to DOM/template/JSX/whatever...

}

@POST @Path ( "/api/move" ) fun Game move( @QueryParam( "id" ) id: Long, @QueryParam( "row" ) row: Int, @QueryParam( "col" ) col: Int) {

// TODO check business logic, persist, return udpated game ... }

Android iOS Web iOS Web Server / API Android View Models Presenters Client Backend Business Logic Models

X
O
X

X X O O O
X

twitter.com/ github.com/ .com Possible Futures with Kotlin

jakewharton jakewharton jakewharton