scala - usp · basic types operators are methods 1 + 2 invokes 1.+(2) ... (l 2) yield l scala...

25
Scala Fernando Medeiros – [email protected] Tomás Paim – [email protected]

Upload: dongoc

Post on 08-Mar-2019

219 views

Category:

Documents


0 download

TRANSCRIPT

ScalaFernando Medeiros – [email protected]

Tomás Paim – [email protected]

Topics

A Scalable Language

Classes and Objects

Basic Types

Functions and Closures

Composition and Inheritance

Scala’s Hierarchy

Types Parametrization

Traits

Annotations

Assertions and Unit Testing

A Scalable Language

Name stands for “scalable language”

Compiles to JVM bytecodes

Object-oriented

Follows Smalltalk concept

Combines data with operations under a formalized interface

Functional

A Scalable Language

Concise

Compatible with Java – designed for interoperability with Java, as Scala

can inherit from Java classes, call Java methods, access Java fields and

implement Java interfaces

Statically typed – even though compiler can infer return types, is a good

practice to make it explicit

Allows generics

A Scalable Language

// Java class definition

class MyClass {

private: int index;

private: String name;

public MyClass(int index, String name) {

this.index = index;

this.name = name;

}

}

// Scala class definition

class MyClass(index: Int, name: String)

Classes and Objects

Syntax similar to Java…

To instantiate an object of a class:

val myObj = new MyClass(42, “foo”)

But not that much

Inside classes or companion object, what is not private, is public by default

val members cannot have their value modified, while var ones may have

Singleton object definition is one-liner

Classes may have a singleton object companion

Classes and Objects

class MyClass(index: Int, name:

String) {

def doubleFoo = MyClass.foo * 2

def baz {

println("baz")

}

}

object MyClass {

def foo: Int = 42

def bar = "bar"

def newBaz {

val myClassObject = new MyClass(42, "foo")

myClassObject.baz

}

}

Basic TypesBasic Types

Value Type Range

Byte 8-bit signed two’s complement integer (-27 to 27 - 1, inclusive)

Short 16-bit signed two’s complement integer (-215 to 215 - 1,

inclusive)

Int 32-bit signed two’s complement integer (-231 to 231 - 1,

inclusive)

Long 64-bit signed two’s complement integer (-263 to 263 - 1,

inclusive)

Char 16-bit unsigned Unicode character (0 to 216 - 1, inclusive)

String a sequence of Chars

Float 32-bit IEEE 754 single-precision float

Double 64-bit IEEE 754 double-precision float

Boolean true or false

Basic Types

Operators are methods

1 + 2 invokes 1.+(2)

Any method can be an operator

Str.indexOf(‘o’) – method is being invoked

Str indexOf ‘o’ – indexOf is an operator

Functions and Closures

Functions are first-class values

Scala offers several ways to break the code into smaller pieces

Methods

Local and anonymous functions

def factorial(n: Int): Int = {

def loop(n: Int, acc: Int): Int = if (n < 1) acc else loop(n - 1, n * acc)

loop(n, 1)

}

Functions and Closures

Chain calls

def stdev(l: List[Double]): Double = scala.math.pow(l.map(_ - l.sum /

l.length).map(scala.math.pow(_, 2)).sum / (l.length), .5)

Closures

Yield keyword may be used to return some value to a code block

Both expressions below are equivalent:

list.filter(_ > 2)

for (l <- list if l > 2) yield l

Scala offers lazy evaluation of vals and functions arguments

Functions and Closures

Composition and Inheritance

Inheritance in Scala works in a way similar to Java, using keyword

“extends”. Even though it doesn’t allow multiple inheritance, traits can be

mixed in with classes

There is the concept of “abstract class”, where there may be

unimplemented methods

An abstract class can’t be instantiated. It is required to extend it to a

concrete class, then instantiate the concrete one

Functions can be overridden in subclasses, using keyword “override” (final

keyword is used to disallow overriding a method, or extending a class)

“toString” method may be overridden in any class, to customize the way

you print the elements of the class

Composition and Inheritance

Composition and Inheritance One way to create composition relationship between classes in Scala is

through abstract classes

abstract class Element {

def contents: Array[String]

val height = contents.length

val width = if (height == 0) 0 else contents(0).length

}

class ArrayElement(conts: Array[String]) extends Element {

def contents: Array[String] = conts

}

Scala’s Hierarchy

Types Parametrization

It is possible to parametrize classes with types parameters bounds, in the

case of generic parametrization.

T <: Type

The parameter passed as T must be something more specific than

type Type, i.e. below the hierarchy of Type

T >: Type

The parameter passed as T must be something more generic than

type Type, i.e. above the hierarchy of Type

Types Parametrizationclass Stone

class Pebble extends Stone

class Container[T <: Pebble]

val contPebble = new Container[Pebble]

val contStone = new Container[Stone]

Types Parametrizationclass Stone

class Pebble extends Stone

class Container[T >: Pebble]

val contPebble = new Container[Pebble]

val contStone = new Container[Stone]

Traits

Traits encapsulate methods and field definitions, that can be reused by

mixing them into classes.

Commonly used when a class needs some behavior orthogonal to the class

purpose. They are mixed with classes by keyword “with”.

Not used to extend Java code directly, as there is not a direct Java

equivalent of traits

Traits

Example:

trait Singer { def sing: Unit = println("Sings") }

abstract class Animal { def eat: Unit }

abstract class Person { def think: Unit }

class Bird(specie: String) extends Animal with Singer { def eat: Unit =

println(s"${this.specie} is eating") }

class Actor(name: String) extends Person with Singer { def think: Unit =

println(s"${this.name} is acting") }

Annotations

Automatic generation of documentation with Scaladoc

@deprecated def bigMistake = ...

Ensuring code properties

@tailrec //this code compiles

def factorial(n: Int): Int = {

def loop(n: Int, acc: Int): Int = if (n < 1) acc else loop(n - 1, n * acc)

loop(n, 1)

}

@tailrec //compiler shows error in this case, as this is not a tail recursive call

def factorial(n: Int): Int = {

if (n < 2) 1 else n * factorial(n - 1)

}

Assertions and Unit Testing

There are several frameworks for Scala code testing:

Unit tests

JUnit

TestNG

Behavior tests

Spec

WordSpec

FlatSpec

Property-based testing

ScalaCheck

References

Programming in Scala. Odersky, Spoon and Venners

Scala for the Impatient. Horstmann

http://scala-lang.org/

Further Reading

Functional Programming in Scala. Chiusano and Bjarnason

Design patterns in Scala

http://www.scala-lang.org/old/sites/default/files/FrederikThesis.pdf

https://pavelfatin.com/design-patterns-in-scala