So different polymorphism in Scala
description
Transcript of So different polymorphism in Scala
![Page 1: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/1.jpg)
So different polymorphism
in Scala
Boris Trofimov
@b0ris_1
www.btrofimoff.com
![Page 2: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/2.jpg)
Scala has at least 9 kinds of
polymorphism
Don’t believe?
Let’s dig in
![Page 3: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/3.jpg)
Agenda
Why Scala?
A few words about definition
Classic polymorphism
Parametric polymorphism
Reflection polymorphism
Functional polymorphism
Duck polymorphism
Enhanced Ad-hoc polymorphism
Type class polymorphism
Parametric polymorphism of the 2nd kind
F-bounded polymorphism
![Page 4: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/4.jpg)
Why Scala?
Object-Oriented Meets Functional
Strong Functional
It makes you love your code again
Scalable grammar
Hello Domain Specific Languages (DSL)
Inexhaustible language for every day
![Page 5: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/5.jpg)
Basic Degree
![Page 6: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/6.jpg)
Definition
Ability of language to handle data of different types in the same
way.
Provision of a single interface to entities of different types.
Particular code is able to handle data of different types.
Way to change code behavior via input parameters without
modifications
![Page 7: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/7.jpg)
Classic polymorphism
Ad-hoc
Subtyping
class A{
def method {
...
this.doSomething
...
}
// abstract method
def doSomething
}
class B extends A{
override def doSomething {}
}
class B extends C{
override def doSomething {}
}
class A
class B extends A
class C extends A
class List{
def add(a : A) {
...
}
}
![Page 8: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/8.jpg)
Parametric polymorphism
class MyClass{
def addItem[A](a:A) = {
val list = new ListBuffer[A]
list +=a
list
}
def addItem[B <: ParentClass] (b:B) = {
val list = new ListBuffer[B]
list +=b
list
}
}
![Page 9: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/9.jpg)
Reflection polymorphism (ugly version)
class MyClass{
def doSomething(a: Object){
...
val method = a.getClass().getMethod(“run”, Int);
method.invoke(a, 1);
...
}
}
![Page 10: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/10.jpg)
Functional polymorphism
class A ( sortFunc: List[Int] => List[Int] ){
def doSomething(data : List[Int]) = {
...
sortFunc(data)
...
}
}
object BubbleSort{
def sort(a:List[Int]) : List[Int] = { ... }
}
object QuickSort{
def sort(a:List[Int]) : List[Int] = { ... }
}
object Application{
def main(){
val a = new A(BubbleSort.sort(_))
a.doSomething(List(1,2,3))
}
}
object Sorter{
def sort( list : List[Int],
data : (Int,Int) => Int ) : List[Int] = {
...
}
}
object Application{
def main(){
val list = List(7,8,5,4)
Sorter.sort(list, (a,b) => a-b)
}
}
![Page 11: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/11.jpg)
Hello Scala
or Bachelor degree
![Page 12: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/12.jpg)
Duck polymorphism
When I see a bird that walks like a duck and swims like a duck
and quacks like a duck, I call that bird a duck
Scala structural types
Caution: Reflection!
class MyClass{
def doSomething(a : type { def run(i : Int) } ){
...
a.run(1)
...
}
}
class DuckClass {
def run(i : Int) {
...
}
}
![Page 13: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/13.jpg)
Type constructor polymorphism
trait ParentTrait{
type T
type MapperType =
com.apache.hadoop.Mapper[LongWritable,Text,AvroKey[CharSequence],AvroValue[T]]
type Context = MapperType#Context
...
}
object CustomMapperObject extends ParentTrait{
type T = Pair[String,String]
class CustomMapper extends MapperType {
override def setup(context:Context) = {
...
}
override def map(key:LongWritable, value:Text, context:Context) = {
...
}
}
}
Type variables defined in sibling classes
Building another types dependent on type variables
![Page 14: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/14.jpg)
Enhanced Ad-hoc polymorphism -Intro
Inheritance vs Composition
Mixin pattern – a way to inject
some code into class impl.
Scala supports Mixin (Trait)
Trait – is like interface +
implementation with multiple
trait inheritance and without
head pain
trait Utils{
def printList[A](list: List[A]) =
list.foreach (a => System.Console.println(a))
}
trait LogTrait {
lazy val logger =
LoggerFactory.getLogger(this.getClass.getName)
def setLogLevel(level : Level) =
Logger.getRootLogger.setLevel(level)
}
class MyClass extends LogTrait with Utils{
def do(){
logger.info("hello world!");
printList List(1,2,3,4,5,6)
}
}
![Page 15: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/15.jpg)
Enhanced Ad-hoc polymorphism – Continue
or welcome to Cake pattern trait ComponentA{
def doThis() : String
}
trait ComponentB{
def doThat() : String
}
class OurComponent extends ComponentA with ComponentB{
def doSomething() = doThis() + doThat()
}
trait ComponentAImpl extends ComponentA{
def doThis() = "hello Component A"
}
trait ComponentBImpl extends ComponentB{
def doThat() = "hello Component B"
}
object Main {
def main() {
val obj = new OurComponent with ComponentAImpl with ComponentBImpl
println(obj.doSomething())
}
}
![Page 16: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/16.jpg)
Master degree
![Page 17: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/17.jpg)
Type class polymorphism – Intro Way to create generalized methods with partial specialization
Way to have some logic which cannot be added to origin class T (for
instance tricky serialization)
trait NumericLike[T] {
def plus(x : T, y: T) : T
}
implicit object TInteger extends NumericLike[Int]{
def plus(x : Int, y: Int) : Int = x + y
}
implicit object TString extends NumericLike[String]{
def plus(x : String, y: String) : String = x + y
}
object Arithmetics{
// generalized `add` method
def add[T](x:T, y:T)(implicit engine : NumericLike[T]) = engine.plus(x, y)
}
object Test{
println( Arithmetics.add("Hello", " World") ) // returns HelloWorld
println( Arithmetics.add(2,3) ) // returns 5
// Compile Error, could not find corresponding implicit object
println( Arithmetics.add(123.0, -45.345) )
}
![Page 18: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/18.jpg)
Type class polymorphism – Continue
or inventing DI class ComponentA{
...
}
class ComponentB{
...
}
class ComponentC (implicit componentA: ComponentA, componentB: ComponentB){
...
}
object LiveContext{
implicit val componentA = new ComponentA()
implicit val componentB = new ComponentB()
implicit val componentC = new ComponentC()
}
object TestContext{
implicit val componentA = mock[ComponentA]
implicit val componentB = mock[ComponentB]
implicit val componentC = new ComponentC()
}
![Page 19: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/19.jpg)
Parametric polymorphism of the 2nd kind
Way to build generalized types to take generics as parameters
trait ContainerHandler[M[_]] {
def put[A](x: A): M[A]
def get[A](m: M[A]): A
}
implicit val listHandler =
new ContainerHandler[List]{ def put[A](x: A) = List(x); def get[A](m: List[A]) = m.head }
implicit val optionHandler =
new ContainerHandler[Some]{ def put[A](x: A) = Some(x); def get[A](m: Some[A]) = m.get }
object Operations{
def tupleize[M[_]: ContainerHandler, A, B](fst: M[A], snd: M[B]) = {
val engine = implicitly[ContainerHandler[M]]
engine.put( Pair(engine.get(fst), engine.get(snd)) )
}
}
object Test{
Operations.tupleize(Some(1), Some(2)) // returns Some( (1,2) )
Operations.tupleize(List(1), List (2)) //returns List( (1,2) )
}
![Page 20: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/20.jpg)
trait Ordered[T]{
def compare(that: T): Int
}
class MyContainer extends Ordered[MyContainer] {
def compare(that: MyContainer): Int = { ... }
}
F-bounded polymorphism – Intro
How to define a polymorphic function that, though defined in terms of
a supertype, will when passed a value of some subtype will always
return/take a value of the same subtype as its argument.
Simplest example:
F-bounded polymorphism plus existential types allows building
generalized functions which process collections of different types(!)
![Page 21: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/21.jpg)
F-bounded polymorphism – Continue trait Account[T <: Account[T]] {
def addFunds(amount: BigDecimal): T
}
class CheckingAccount(total: BigDecimal, trxMaxCount: Int) extends Account[CheckingAccount] {
def addFunds(amount: BigDecimal) : CheckingAccount = new CheckingAccount(total + amount, trxMaxCount)
}
class SavingAccount(total: BigDecimal) extends Account[SavingAccount] {
def addFunds(amount: BigDecimal) : SavingAccount = new SavingAccount(total + amount)
}
object Account {
val feePercentage = BigDecimal("0.02")
val feeThreshold = BigDecimal("10000.00")
def deposit[T <: Account[T]](amount: BigDecimal, account: T): T = {
if (amount < feeThreshold) account.addFunds(amount - (amount * feePercentage))
else account.addFunds(amount)
}
def debitAll(amount: BigDecimal,
accounts: List[T forSome { type T <: Account[T] }]): List[T forSome { type T <: Account[T] }] = {
accounts map { _.addFunds(-amount) }
}
}
object Test {
def main(argv: Array[String]): Unit = {
Account.debitAll(BigDecimal("10.00"),
List[T forSome { type T <: Account[T] }](
new CheckingAccount(BigDecimal("0"), 10), new SavingAccount(BigDecimal("0"))))
}
}
![Page 22: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/22.jpg)
Referencies
Martin Odersky Programming in Scala
http://twitter.github.io/scala_school/advanced-types.html
http://logji.blogspot.com/2012/11/f-bounded-type-polymorphism-
give-up-now.html
http://danielwestheide.com/blog/2013/02/06/the-neophytes-
guide-to-scala-part-12-type-classes.html
![Page 23: So different polymorphism in Scala](https://reader033.fdocuments.in/reader033/viewer/2022051512/53fe2b7c8d7f72db2d8b4625/html5/thumbnails/23.jpg)
Thank you!
Q&A