Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Usando Delegations no Kotlin

Usando Delegations no Kotlin

Kotlin provê o Delegation pattern por padrão na linguagem, nessa apresentação aprenderemos o conceito de Delegation, o que é Delegation properties e como extrair todo o potencial dessa feature do Kotlin.

Felipe Rodrigues

July 19, 2017
Tweet

More Decks by Felipe Rodrigues

Other Decks in Programming

Transcript

  1. O Problema interface Auth { void login(); } class Client

    implements Auth { String firstName, lastName, username, email; @Override public void login() { } }
  2. O Problema interface Auth { void login(); } interface Access

    { boolean isAdmin(); } class Client implements Auth, Access { String firstName, lastName, username, email; @Override public void login() { } @Override public boolean isAdmin() { } }
  3. O Problema interface Auth { void login(); } interface Access

    { boolean isAdmin(); } interface Finances { long balance(); } class Client implements Auth, Access, Finances { String firstName, lastName, username, email; @Override public void login() { } @Override public boolean isAdmin() { } @Override public long balance() { } }
  4. Delegation? “ Delegation is an implementation mechanism in which an

    object forwards or delegates a request to another object. ”
  5. interface Loggable { public void log(String message); } class ConsoleLogger

    implements Loggable { @Override public void log(String message) { System.out.println(message); } } class ToastLogger implements Loggable { Context context; public ToastLogger(Context context) { this.context = context; } @Override public void log(String message) { Utils.showToast(context, message); } }
  6. interface Loggable { public void log(String message); } class ConsoleLogger

    implements Loggable { @Override public void log(String message) { System.out.println(message); } } class ToastLogger implements Loggable { Context context; public ToastLogger(Context context) { this.context = context; } @Override public void log(String message) { Utils.showToast(context, message); } } class Worker implements Loggable { public Loggable logger; public Worker(Loggable logger) { this.logger = logger; } @Override public void log(String message) { logger.log(message); } public void doWork() { log( "Working"); } }
  7. interface Loggable { public void log(String message); } class ConsoleLogger

    implements Loggable { @Override public void log(String message) { System.out.println(message); } } class ToastLogger implements Loggable { Context context; public ToastLogger(Context context) { this.context = context; } @Override public void log(String message) { Utils.showToast(context, message); } } class Worker implements Loggable { public Loggable logger; public Worker(Loggable logger) { this.logger = logger; } @Override public void log(String message) { logger.log(message); } public void doWork() { log( "Working"); } } Worker worker = new Worker(new ConsoleLogger()); worker.logger = new ToastLogger(getContext()); worker.doWork();
  8. Pra que usar isso? - Reusabilidade; - Baixo Acoplamento; -

    Herança Dinâmica; - Separação de Responsabilidade;
  9. interface Loggable { public void log(String message); } class ConsoleLogger

    implements Loggable { @Override public void log(String message) { System.out.println(message); } } class ToastLogger implements Loggable { Context context; public ToastLogger(Context context) { this.context = context; } @Override public void log(String message) { Utils.showToast(context, message); } } class Worker implements Loggable { public Loggable logger; public Worker(Loggable logger) { this.logger = logger; } @Override public void log(String message) { logger.log(message); } public void doWork() { log( "Working"); } } Worker worker = new Worker(new ConsoleLogger()); worker.logger = new ToastLogger(getContext()); worker.doWork();
  10. interface Loggable { fun log(message: String) } class ConsoleLogger :

    Loggable { override fun log(msg: String) = println(msg) } class ToastLogger(val context: Context) : Loggable { override fun log(msg: String) = toast(msg) } class Worker(var logger: Loggable) : Loggable by logger { fun doWork() { log("Working...") } } val worker = Worker(ConsoleLogger()) worker.logger = ToastLogger(context) worker.doWork()
  11. Como usar class NameDelegate() { var name: String = "Felipe"

    operator fun getValue(ref: Any?, prop: KProperty<*>): String { println("valor '$value' de '${prop.name}'sendo entregue para $ref") return name } operator fun setValue(ref: Any?, prop: KProperty<*>, value: String) { println("’$value’ atribuido à ‘${prop.name}’ em $ref.'") name = value } } val name: String by NameDelegate()
  12. Como usar class NameDelegate() { var name: String = "Felipe"

    operator fun getValue(ref: Any?, prop: KProperty<*>): String { println("valor '$value' de '${prop.name}'sendo entregue para $ref") return name } operator fun setValue(ref: Any?, prop: KProperty<*>, value: String) { println("’$value’ atribuido à ‘${prop.name}’ em $ref.'") name = value } } val name: String by NameDelegate()
  13. Como usar class NameDelegate() { var name: String = "Felipe"

    operator fun getValue(ref: Any?, prop: KProperty<*>): String { println("valor '$value' de '${prop.name}'sendo entregue para $ref") return name } operator fun setValue(ref: Any?, prop: KProperty<*>, value: String) { println("’$value’ atribuido à ‘${prop.name}’ em $ref.'") name = value } } var name: String by NameDelegate()
  14. Como usar class NameDelegate(): ReadWriteProperty<Any?, String> { // ou ReadOnlyProperty

    var name: String = "Felipe" override fun getValue(ref: Any?, prop: KProperty<*>): String { println("valor '$value' de '${prop.name}'sendo entregue para $ref") return name } override fun setValue(ref: Any?, prop: KProperty<*>, value: String) { println("’$value’ atribuido à ‘${prop.name}’ em $ref.'") name = value } } val name: String by NameDelegate()
  15. Delegations Properties Padrão • Lazy val database: Database by lazy

    { println("created!") Database() } fun main(args: Array<String>) { println(database.isConnected()) println(database.isConnected()) }
  16. Delegations Properties Padrão • Lazy val database: Database by lazy

    { println("created!") Database() } fun main(args: Array<String>) { println(database.isConnected()) println(database.isConnected()) } Output: created! false false
  17. Delegations Properties Padrão • Observable import kotlin.properties.Delegates class User {

    var name: String by Delegates.observable( "Sicrano") { prop, oldValue, newValue -> println("$oldValue -> $newValue") } } val user = User() user.name = "Fulano" user.name = "Beltrano"
  18. Delegations Properties Padrão • Observable import kotlin.properties.Delegates class User {

    var name: String by Delegates.observable( "Sicrano") { prop, oldValue, newValue -> println("$oldValue -> $newValue") } } val user = User() user.name = "Fulano" user.name = "Beltrano" Output: Sicrano -> Fulano Fulano -> Beltrano
  19. Delegations Properties Padrão • Armazenar em um Map class User(val

    map: Map<String, Any?>) { val name: String by map val age: Int by map } val user = User(mapOf( "name" to "John Doe", "age" to 25 )) println("Name: ${user.name}, Age: ${user.age}")
  20. Delegations Properties Padrão • Armazenar em um Map class User(val

    map: Map<String, Any?>) { val name: String by map val age: Int by map } val user = User(mapOf( "name" to "John Doe", "age" to 25 )) println("Name: ${user.name}, Age: ${user.age}") Output: Name: John Doe, Age: 25
  21. Libs usando delegations • KotPref (github.com/chibatching/Kotpref) object UserInfo : KotprefModel()

    { var name by stringPref() var code by nullableStringPref() var age by intPref(default = 14) var highScore by longPref() var rate by floatPref() val prizes by stringSetPref { val set = TreeSet<String>() set.add( "Beginner") set } } UserInfo.name = "User" UserInfo.code = "Test"