Typing in Java, Kotlin and Scala

Post on 05-Apr-2017

141 views 2 download

Transcript of Typing in Java, Kotlin and Scala

Typing in Java,Kotlin and Scala

Hanneli Tavante

Breandan Considine

Hi!@breandan @hannelita

DisclaimerWe will work on a single example

and rebuild it several times

It is not a language war!

We are going to discusssome architecture concepts

Agenda

Representing Layouts in JavaMoving to KotlinCovariance and contravariance in ScalaCovariance and contravariance in KotlinByteCode and type erasureWhy is this important?

Mobile

Vertical Horizontal

Layout

How can werepresent that in

Java?

Layout

Vertical

Horizontal

class Layout { //superclass}

class Vertical extends Layout {

}

class Horizontal extends Layout {

}

Vertical

Horizontal

Layout

Inheritance... mehTight couplingReusing base class for unrelated child

Can we come up with abetter layout?

class Vertical implements Layout {

}

interface Layout {

}

class Horizontal implements Layout {

}

Vertical

Horizontal

Layout

Does this objecthave these skills?

Does this objectunderstand this

protocol ?

Name refactor

class Vertical implements Orientation {

}

interface Orientation {

}

class Horizontal implements Orientation {

}

It is time to addsome methods

rotate()

rotate() applied to a Horizontal -> Vertical

rotate() applied to a Vertical -> Horizontal

Where should weplace the method

rotate() ?

class Vertical implements Orientation {

}

interface Orientation {

}

class Horizontal implements Orientation {

}

class Vertical implements Orientation {

Horizontal rotate() { return new Horizontal(); }

}

interface Orientation {

}

class Horizontal implements Orientation {

Vertical rotate() { return new Vertical(); }

}

class Vertical implements Orientation {

Horizontal rotate() { return new Horizontal(); }

}

interface Orientation { Orientation rotate();

}

class Horizontal implements Orientation {

Vertical rotate() { return new Vertical(); }

}

Can we make itbetter?

We also could useGenerics

class Layout<T> {

}

class Layout<T> {

}

class Vertical {

}

class Horizontal {

}

Layout

Vertical

Horizontal

How do we restrict aLayout either

Layout<Vertical> orLayout<Horizontal>

class Vertical implements Orientation {

}

interface Orientation {

}

class Horizontal implements Orientation {

}

class Layout<T extends Orientation> {

}

Can we have a generic Layout rotate() ?

class Vertical implements Orientation {

Horizontal rotate() { return new Vertical(); }}

class Horizontal implements Orientation {

Vertical rotate() { return new Horizontal(); }}

interface Orientation { Orientation rotate();}

class Layout<T extends Orientation> { public Layout(T t){ this.t = t; } Orientation rotate(){ t.rotate(); }}

We want to achieve:

Layout<Horizontal> layoutHorizontal = new Layout<Horizontal>(new Horizontal());

layoutHorizontal.rotate();

layoutHorizontal.rotate();Orientation result

=Layout<Vertical> layoutvertical

We want:(Layout<Vertical>)

=

Explicit casting

:(

Is there any wayto avoid that?

Agenda

Representing Layouts in JavaMoving to KotlinCovariance and contravariance in ScalaCovariance and contravariance in KotlinByteCode and type erasureWhy is this important?

In Kotlin:

class Vertical : Orientation { override fun rotate() = Horizontal()}

class Horizontal : Orientation { override fun rotate() = Vertical()}

interface Orientation { fun rotate(): Orientation}

class Layout<out T : Orientation>(val t: T) {}

In Kotlin:class Layout<out T : Orientation>(val t: T) {}

In Kotlin:class Layout<out T : Orientation>(val t: T) {}

@JvmName("rotateVertical")fun Layout<Horizontal>.rotate(): Vertical = this.t.rotate()

@JvmName("rotateHorizontal")fun Layout<Vertical>.rotate(): Horizontal = this.t.rotate()

Extension functions

In Kotlin:val horizontal = Layout(Horizontal())val vertical = Layout(Vertical())

// Type safe rotation!var v: Layout<Vertical> = horizontal.rotate()var h: Layout<Horizontal> = vertical.rotate()h = horizontal.rotate().rotate()v = vertical.rotate().rotate()

In Kotlin:val horizontal = Layout(Horizontal())val vertical = Layout(Vertical())

// Type safe rotation!var v: Layout<Vertical> = horizontal.rotate()var h: Layout<Horizontal> = vertical.rotate()h = horizontal.rotate().rotate()v = vertical.rotate().rotate()

/* Does not compile!v = horizontal.rotate().rotate()h = vertical.rotate().rotate()*/

Agenda

Representing Layouts in JavaMoving to KotlinCovariance and contravariance in ScalaCovariance and contravariance in KotlinByteCode and type erasureWhy is this important?

Redesign In Scala:trait Orientation {}

Redesign In Scala:trait Orientation {}

class Vertical extends Orientation {}

class Horizontal extends Orientation {}

Redesign In Scala:trait Orientation {}

class Vertical extends Orientation {}

class Horizontal extends Orientation {}

abstract class Layout[+T <: Orientation] { def layout: T}

Redesign In Scala:trait Orientation {}

class Vertical extends Orientation {}

class Horizontal extends Orientation {}

abstract class Layout[T <: Orientation] { def layout: T}

class VerticalLayout(v: Vertical) extends Layout[Vertical] { override def layout = v}

class HorizontalLayout(h: Horizontal) extends Layout[Horizontal] { override def layout = h}

Orientation

Vertical

Horizontal

Orientation

Vertical

Horizontal

Layout

Horizontal

Layout

Vertical

Orientation

LayoutVertical LayoutHorizontal

In Scalaval layout: Layout[Orientation] = new HorizontalLayout(new Horizontal)

Compile error: "Expression doesn't conformto the expected type"

In Scalaval layout: Layout[Orientation] = new HorizontalLayout(new Horizontal)

abstract class Layout[T <: Orientation] { def layout: T}

We need to tell the compiler thatLayout[Horizontal] is a subtype

Layout[Orientation]

In Scalaval layout: Layout[Orientation] = new HorizontalLayout(new Horizontal)

abstract class Layout[+T <: Orientation] { def layout: T}

We need to tell the compiler thatLayout[Horizontal] is a subtype

Layout[Orientation]

(Covariance)

In Scalaabstract class Layout[+T <: Orientation] { def layout: T

def rerender(layout: T)}

Method to re-render the actual screen,keeping the layout.

In Scalaabstract class Layout[+T <: Orientation] { def layout: T

def rerender(layout: T)}

Compile error: "Covariant type occurs incontravariant position"

In Scalaabstract class Layout[+T <: Orientation] { def layout: T

def rerender[T >: Orientation](layout: T)

}

Why does the injected argument needs tobe contravariant?

In Scalaabstract class Layout[+T <: Orientation] { def layout: T

def rerender(layout: T)

}

var layoutWrapper: Layout[Orientation] = new HorizontalLayout(new Horizontal) layoutWrapper.rerender(new Vertical)

^That is not right.That is why input arguments are

contravariant.

Scala and Kotlin helpyou actively thinkabout covariance

and contravariance

Agenda

Representing Layouts in JavaMoving to KotlinCovariance and contravariance in ScalaCovariance and contravariance in KotlinByteCode and type erasureWhy is this important?

Back to Kotlininterface Orientation { fun rotate(): Orientation}

object Vertical : Orientation { override fun rotate() = Horizontal}

object Horizontal : Orientation { override fun rotate() = Vertical}

Back to Kotlininterface Orientation { fun rotate(): Orientation}

object Vertical : Orientation { override fun rotate() = Horizontal}

object Horizontal : Orientation { override fun rotate() = Vertical}

class Layout<out T : Orientation>(val t: T) {}

Back to Kotlinopen class Builder<out T : Layout<*>> { open fun build(): T = build()}

Back to Kotlinopen class Builder<out T : Layout<*>> { open fun build(): T = build()}

open class Renderer<in T> { open fun render(t: T) { println(t) }}

Back to Kotlinopen class Builder<out T : Layout<*>> { open fun build(): T = build()}

open class Renderer<in T> { open fun render(t: T) { println(t) }}

fun covariance(horizontalBuilder: Builder<Layout<Horizontal>>, layoutBuilder: Builder<Layout<Orientation>>) { // Layout<Horizontal> is a subtype of Layout<Orientation> ✓ val bldr: Builder<Layout<Orientation>> = horizontalBuilder // Layout<Orientation> is a supertype of Layout<Horizontal> ✗ val hlbr: Builder<Layout<Horizontal>> = layoutBuilder //ERROR}

Back to Kotlinopen class Builder<out T : Layout<*>> { open fun build(): T = build()}

open class Renderer<in T> { open fun render(t: T) { println(t) }}

fun contrav(layoutRenderer: Renderer<Layout<Orientation>>, horizontalRenderer: Renderer<Layout<Horizontal>>) { // Layout<Orientation> is a supertype of Layout<Horizontal> ✓ val hlrd: Renderer<Layout<Horizontal>> = layoutRenderer // Layout<Horizontal> is a subtype of Layout<Orientation> ✗ val lrdr: Renderer<Layout<Orientation>> = horizontalRenderer}

Agenda

Representing Layouts in JavaMoving to KotlinCovariance and contravariance in ScalaCovariance and contravariance in KotlinByteCode and type erasureWhy is this important?

JVM Languageswill loose the T

parameter! class Layout {}

(type erasure)

StrategiesTypeTags and Shapeless libraries in ScalaExtension functions in KotlinReified generics in KotlinReflectionManually store T in a field

Agenda

Representing Layouts in JavaMoving to KotlinCovariance and contravariance in ScalaCovariance and contravariance in KotlinByteCode and type erasureWhy is this important?

To sum up

Think about different coding approachesDifferent architecturesNew conceptsUnderstand the goods and the bad parts of alanguage and when to use each of them

Thank you :)Questions?