Slide 1

Slide 1 text

FORGOTTEN TRAITS Михаил Розумянский 1

Slide 2

Slide 2 text

ПРИМЕСЬ (MIXIN) Subclass Mixin Base Class Mixin 2

Slide 3

Slide 3 text

TRAIT Отсутствие состояния Ограничение базового класса Переопределение методов базового класса Вызов методов базового класса Модификаторы доступа 3

Slide 4

Slide 4 text

ОБЪЯВЛЕНИЕ trait CollectionWithComparator> : AbstractCollection { protected val comparator: Comparator override fun contains(element: E): Boolean { return any { comparator.compare(it, element) == 0 } } } 4

Slide 5

Slide 5 text

ИСПОЛЬЗОВАНИЕ class CaseInsensitiveStringCollection : AbstractCollection(), CollectionWithComparator { override val comparator = String.CASE_INSENSITIVE_ORDER // ... } 5

Slide 6

Slide 6 text

ЧЕМ ЗАМЕНИТЬ? 6

Slide 7

Slide 7 text

НИЧЕМ 7

Slide 8

Slide 8 text

А НА САМОМ ДЕЛЕ? 8

Slide 9

Slide 9 text

ЗАДАЧА Manager Worker Employee delegates implements implements 9

Slide 10

Slide 10 text

ДЕЛЕГАТ Manager Worker Employee delegates implements implements 10

Slide 11

Slide 11 text

11

Slide 12

Slide 12 text

СОТРУДНИК interface Employee { fun performTask(task: String) } abstract class AbstractEmployee(val name: String) : Employee { fun say(text: String, vararg arguments: String) { Output.write(name, text, *arguments) } } 12

Slide 13

Slide 13 text

JAVA WAY 13

Slide 14

Slide 14 text

WORKER public class Worker extends AbstractEmployee { public Worker(final String name) { super(name); } @Override public void performTask(final String task) { say("I had to %s and I've just done it.", task); } } 14

Slide 15

Slide 15 text

MANAGER public class Manager extends AbstractEmployee { private final Employee delegate = new Worker("Dilbert"); public Manager(final String name) { super(name); } @Override public void performTask(@NotNull final String task) { delegate.performTask(task); } public void manageTask(@NotNull final String task) { say("Hey, %s.", task); performTask(task); say("It's just a piece of cake to %s.", task); } } 15

Slide 16

Slide 16 text

MAIN public class Demo { public static void main(final String[] args) { final Manager manager = new Manager("Boss"); for (final String task : args) { manager.manageTask(task); } } } 16

Slide 17

Slide 17 text

Boss Hey, prepare a presentation. Dilbert I had to prepare a presentation and I've just done it. Boss It's just a piece of cake to prepare a presentation. 17

Slide 18

Slide 18 text

KOTLIN WAY 18

Slide 19

Slide 19 text

WORKER class Worker(name: String) : AbstractEmployee(name) { override fun performTask(task: String) { say("I had to $task and I've just done it.") } } 19

Slide 20

Slide 20 text

MANAGER class Manager( name: String ) : AbstractEmployee(name), Employee by Worker("Dilbert") { fun manageTask(task: String) { say("Hey, $task.") performTask(task) say("It's just a piece of cake to $task.") } } 20

Slide 21

Slide 21 text

ЧТО ВНУТРИ? public final class Manager extends AbstractEmployee { private final Worker $$delegate_0 = new Worker("Dilbert"); public Manager(@NotNull String name) { super(name); } @Override public void performTask(@NotNull String task) { $$delegate_0.performTask(task); } public final void manageTask(@NotNull String task) { say("Hey, " + task + '.'); performTask(task); say("It's just a piece of cake to " + task + '.'); } } 21

Slide 22

Slide 22 text

ДОСТУП К ДЕЛЕГАТУ 22

Slide 23

Slide 23 text

НОВЫЙ MANAGER class Manager private constructor( name: String, private val delegate: Employee ) : AbstractEmployee(name), Employee by delegate { constructor(name: String) : this(name, Worker("Dilbert")) override fun performTask(task: String) { say("Hey, $task.") delegate.performTask(task) say("It's just a piece of cake to $task.") } } 23

Slide 24

Slide 24 text

МОГЛО БЫ БЫТЬ И ЛУЧШЕ — Distinguish syntactically when delegating to a property — Provide a way to reference a delegate in class body KT-83 KT-18427 24

Slide 25

Slide 25 text

ИЗМЕНЕНИЕ ДЕЛЕГАТА Manager Worker 1 Manager Worker 2 25

Slide 26

Slide 26 text

НАИВНЫЙ ПОДХОД private var delegate: Employee fireAndHire() private fun fireAndHire() { say("Seems I need to fire this guy and hire someone else.") delegate = Worker(Names.next()) } class Manager private constructor( name: String, ) : AbstractEmployee(name), Employee by delegate { constructor(name: String) : this(name, Worker(Names.next())) fun manageTask(task: String) { say("Hey, $task.") performTask(task) say("It's just a piece of cake to $task.") } } 26

Slide 27

Slide 27 text

Boss Hey, prepare a presentation. Dilbert I had to prepare a presentation and I've just done it. Boss It's just a piece of cake to prepare a presentation. Seems I need to fire this guy and hire someone else. Hey, write a speech. Dilbert I had to write a speech and I've just done it. Boss It's just a piece of cake to write a speech. Seems I need to fire this guy and hire someone else. 27

Slide 28

Slide 28 text

НО ПОЧЕМУ? 28

Slide 29

Slide 29 text

ДЕКОМПИЛИРУЕМ private Employee delegate; private final Employee $$delegate_0; $$delegate_0 = delegate; delegate = delegate; $$delegate_0.performTask(task); delegate = new Worker(Names.INSTANCE.next()); public final class Manager extends AbstractEmployee { private Manager(String name, Employee delegate) { super(name); } public Manager(@NotNull String name) { this(name, new Worker(Names.INSTANCE.next()); } public void performTask(@NotNull String task) { } private final void fireAndHire() { say("Seems I need to fire this guy and hire someone else."); } } 29

Slide 30

Slide 30 text

ОКАЗЫВАЕТСЯ Для делегата всегда создаётся поле — Delegation to var field KT-5870 30

Slide 31

Slide 31 text

И ЧТО ЖЕ ДЕЛАТЬ? 31

Slide 32

Slide 32 text

ОЧЕРЕДНОЙ MANAGER private var delegate = Worker(Names.next()) delegate.performTask(task) delegate = Worker(Names.next()) class Manager(name: String) : AbstractEmployee(name) { override fun performTask(task: String) { say("Hey, $task.") say("It's just a piece of cake to $task.") fireAndHire() } private fun fireAndHire() { say("Seems I need to fire this guy and hire someone else.") } } 32

Slide 33

Slide 33 text

ПРЯМО КАК В JAVA public class Manager extends AbstractEmployee { private final Employee delegate = new Worker(Names.INSTANCE.next()); public Manager(final String name) { super(name); } @Override public void performTask(task: String) { say("Hey, %s.", task); delegate.performTask(task); say("It's just a piece of cake to %s.", task); fireAndHire(); } private void fireAndHire() { say("Seems I need to fire this guy and hire someone else."); delegate = Worker(Names.INSTANCE.next()); } } 33

Slide 34

Slide 34 text

ИНТЕРФЕЙСЫ С ЧАСТИЧНОЙ РЕАЛИЗАЦИЕЙ interface DelegatingEmployee : Employee { val delegate: Employee override fun performTask(task: String) { delegate.performTask(task) } } 34

Slide 35

Slide 35 text

КАК РАБОТАЮТ? public interface DelegatingEmployee extends Employee { @NotNull Employee getDelegate(); void performTask(@NotNull String task); final class DefaultImpls { public static void performTask( @NotNull DelegatingEmployee self, @NotNull String task) { self.getDelegate().performTask(task); } } } 35

Slide 36

Slide 36 text

ВТОРАЯ ПОПЫТКА , DelegatingEmployee override var delegate: Employee = Worker(Names.next()) super.performTask(task) delegate = Worker(Names.next()) class Manager(name: String) : AbstractEmployee(name) { override fun performTask(task: String) { say("Hey, $task.") say("It's just a piece of cake to $task.") fireAndHire() } private fun fireAndHire() { say("Seems I need to fire this guy and hire someone else.") } } 36

Slide 37

Slide 37 text

Boss Hey, prepare a presentation. Dilbert I had to prepare a presentation and I've just done it. Boss It's just a piece of cake to prepare a presentation. Seems I need to fire this guy and hire someone else. Hey, write a speech. Wally I had to write a speech and I've just done it. Boss It's just a piece of cake to write a speech. Seems I need to fire this guy and hire someone else. 37

Slide 38

Slide 38 text

ПРЯМО КАК В JAVA 8 public class Manager extends AbstractEmployee, DelegatingEmployee { private final String name; private Employee delegate = new Worker(Names.INSTANCE.next()); public Manager(final String name) { super(name); } @Override public Employee getDeleagate() { return delegate; } @Override public void performTask(final String task) { say("Hey, %s.", task); super.performTask(task); say("It's just a piece of cake to %s.", task); fireAndHire(); } private void fireAndHire() { say("Seems I need to fire this guy and hire someone else."); delegate = Worker(Names.INSTANCE.next()); } } 38

Slide 39

Slide 39 text

ТОЛЬКО НЕМНОГО ХУЖЕ — Generate default methods for implementations in interfaces — Introduce JvmDefault annotation KT-4779 KT-19415 39

Slide 40

Slide 40 text

ДЕЛЕГАТ ДЕЛЕГАТА Manager Worker Expert implements uses 40

Slide 41

Slide 41 text

ПОЯВЛЯЕТСЯ ЭКСПЕРТ interface Expert { fun answer(question: String) } 41

Slide 42

Slide 42 text

РАБОТНИК СПРАШИВАЕТ ЭКСПЕРТА private val expert: Expert ask("What is the theme?") ask("When is the deadline?") private fun ask(question: String) { expert.answer(question) } class Worker( name: String, ) : AbstractEmployee(name) { override fun performTask(task: String) { say("I had to $task and I've just done it.") } say(question) } 42

Slide 43

Slide 43 text

ОЧЕВИДНОЕ РЕШЕНИЕ Employee by Worker("Dilbert", this), Expert override fun answer(question: String) { say(MotivationalQuotes.random()) } class Manager( name: String ) : AbstractEmployee(name), { fun manageTask(task: String) { say("Hey, $task.") performTask(task) say("It's just a piece of cake to $task.") } } 43

Slide 44

Slide 44 text

НЕ РАБОТАЕТ Error: 'this' is not defined in this context — Allow passing this to a class delegate KT-13603 44

Slide 45

Slide 45 text

ИСПРАВЛЯЕМ DelegatingEmployee override val delegate: Employee = Worker("Dilbert", this) class Manager( name: String ) : AbstractEmployee(name), , Expert { fun manageTask(task: String) { say("Hey, $task.") performTask(task) say("It's just a piece of cake to $task.") } override fun answer(question: String) { say(MotivationalQuotes.random()) } } 45

Slide 46

Slide 46 text

Boss Hey, prepare a presentation. Dilbert What is the theme? Boss To win in the marketplace you must first win in the workplace. Dilbert When is the deadline? Boss If it scares you, it might be a good thing to try. Dilbert I had to prepare a presentation and I've just done it. Boss It's just a piece of cake to prepare a presentation. 46

Slide 47

Slide 47 text

ОПЯТЬ КАК В JAVA 8 public class Manager extends AbstractEmployee implements DelegatingEmployee, Expert { private final String name; private final Employee delegate = new Worker("Dilbert", this); public Manager(final String name) { super(name); } public void manageTask(final String task) { say("Hey, %s.", task); performTask(task); say("It's just a piece of cake to %s.", task); } @Override public Employee getDelegate() { return delegate; } @Override public void answer(final String question) { say(MotivationalQuotes.INSTANCE.random()); } } 47

Slide 48

Slide 48 text

В РЕЗУЛЬТАТЕ Наличие состояния Ограничение использования Вызов методов контейнера Модификаторы доступа Отсутствие базового класса Переопределение методов базового класса базового класса 48

Slide 49

Slide 49 text

49

Slide 50

Slide 50 text

СПАСИБО ЗА ВНИМАНИЕ! 50