Buscar

TAP_PL_04 Traits, Case classes Objects

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 5 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Traits, Case classes & Objects
This document provides the basics of case classes, objects and traits. In the examples proposed here,
the classes, objects and traits should go into a scala file. Multiple classes and objects can exist
inside a scala file. The tests in the examples on this document, are simple and can be tried in a scala
worksheet.
Traits
Traits are similar to Java 8’s interfaces. Classes and objects can extend traits but traits cannot be
instantiated.
Traits are a fundamental for code reuse in Scala. They encapsulate method and field definitions,
which can then be reused by mixing them into classes. A class must inherit from just one superclass,
but a class can mix in any number of traits.
A trait can be as simple as:
trait Expr
They could define an abstract values, which every concrete class must implement:
trait Weight {
 def value: Int
 def unit: String
}
The value to implement can become a parameter or an internal value:
final case class KiloGram(value: Int) extends Weight {
 val unit: String = “kg”
}
Or a little more complex:
trait Similarity [A] {
 def isSimilar(e: A): Boolean
 def isNotSimilar(e: A): Boolean = !isSimilar(e)
}
There two methods isSimilar (abstract method) and isNotSimilar with a concrete implementation.
Consequently, classes that integrate this trait only need a concrete implementation for isSimilar.
Notice that this is a generic trait with type A defined as generic.
Thus, the Dog class, if using the Similarity trait, needs to provide an implementation of the method
isSimilar:
final case class Dog(name: String, age: Int) extends Similarity[Dog] {
 override def isSimilar(d: Dog) = this.age == d.age
}
val d1 = Dog("Ace", 3)
val d2 = Dog("Pebbles",5)
val d3 = Dog("Otis", 3)
val d4 = Dog("Ace", 3)
assert(d1.isSimilar(d2)==false)
assert(d1.isSimilar(d3)==true)
Case Classes
Scala class definition is much smaller than the definition in Java. Case classes should be final. Here
an example of a person class:
final case class Person(name: String, zip: Int) {
 def <(p: Person): Boolean = this.name < p.name
}
Case classes in Scala are parameterized with constructor arguments. The two constructor arguments,
name and age, are both public and immutable.
Member functions are public by default. To create a private member function, a private keyword
must be added to its definition.
The class defines a method “>”, (this is a possible method name in Scala) which compares the
person’ names.
Methods toString, equals, hashCode, and copy are automatically generated, but can be supplied.
Case classes are often used with pattern matching mechanisms due to their equality structural
comparisons. Observe the following:
Person("Ana", 20) match {
 case Person(name, zip) => s"Name: $name ; Zip: $zip"
}
//> res0: String = Name: Ana ; Zip: 20
Person("Ana", 20) == Person("Jose", 30)
//> res1: Boolean = false
Person("Ana", 20)== Person("Ana", 20)
//> res2: Boolean = true
An example based on the “Programming in Scala” book will be presented. The domain of interest is
arithmetic expressions consisting of variables, numbers, and unary and binary operations.
sealed trait Expr
final case class Var(name: String) extends Expr
final case class Number(num: Double) extends Expr
final case class UnOp(operator: String, arg: Expr) extends Expr
final case class BinOp(operator: String, left: Expr, right: Expr) extends Expr
The trait being sealed means that it can only be extended on this file. The final keyword has the
same meaning as in Java.
Using the above domain, a function to simplify expressions can be defined:
def simplify(expr: Expr): Expr = expr match {
 case UnOp("-", UnOp("-", e)) => e
 case UnOp("-", Number(n)) if (n<0) => Number(-n)
 case BinOp("*", e, Number(1)) => e
 case BinOp("+", e, Number(0)) => e
 case _ => expr
}
The simplification process can be tested:
simplify(UnOp("-", UnOp("-", Var("x")))) // Var(x)
simplify(UnOp("-", Number(-1))) // Number(1)
simplify(BinOp("+", Number(3.5), Number(0))) // Number(3.5)
simplify(BinOp("*", Number(3.5), Number(1))) // Number(3.5)
In the pattern matching simplify function, patterns are tried in the order in which they were
written, just like the switch case statement in Java. In the second case there is a pattern guard,
which filters only negative numbers. Pattern guards can associate a condition to the pattern
matching and validate only if both the pattern and the condition hold. Once a case is valid, the
result of the pattern matching is found.
Exercises
1. Clone project lab04 and complete the ItemOps object, in the file Item.scala, so that it
passes the tests.
2. Complete the TreeOps object, in the file Tree.scala, so that it passes the tests.
Objects
Singleton Objects
Methods and values that are not associated with individual instances of a class can belong in
singleton objects. This characteristic is achieved by using the keyword object instead of class. A
singleton object definition is similar to a class definition. Here is an example of xml handling in
scala. The function values is supposed to return a list with all the texts contained in elements with a
certain label.
// include xml in scala:
// https://github.com/scala/scala-xml/wiki/Getting-started
object XmlOps {
 def values(xml: scala.xml.Elem, label: String): Seq[String] = {
 for (e <- (xml \\ label)) yield e.text
 }
}
To call the values function, we define an xml object and provide it to the function. The definition of
an xml object in scala can be done using the xml syntax directly :
val xml = <div class="content"><p>Hello</p><p>world</p></div>
XmlOps.values(xml,"p") // List(Hello, world)
Companion Objects
In Java a class with both instance methods and static methods are often needed. In Scala, you
achieve this by having a class and a “companion” object. A singleton object with the same name as
the class is called that class’s companion object. The class and its companion object have to be
defined in the same source file. The class is called the companion class of the singleton object. A
class and its companion object can access each others’ private members.
Smart Constructors
It is common to have companion objects be used as factories for the smart construction of valid
domain objects. For instance, the following definition
final case class DayOfWeek(d: Int)
The d in DayOfWeek is supposed to be 1,2,..,7 but it is possible to build the 23 rd day of week using
the case class.
To limit the classe’s possible values, a smart constructor will be constructed. The class will also be
modified:
final case class DayOfWeek private (d: Int)
object DayOfWeek{
 private def unsafeDayOfWeek(d: Int): DayOfWeek = DayOfWeek(d)
 private val isValid: Int => Boolean = { i => i >= 1 && i <= 7 }
 def from(d: Int): Option[DayOfWeek] = if (isValid(d))
 Some(unsafeDayOfWeek(d)) else None
}
With this definition, the constructor is private, do it is not callable unless from the companion
object. The following call will not compile:
DayOfWeek(1)
Only the following call will compile, but not all will return a valid day of week.
DayOfWeek.from(0) // None
DayOfWeek.from(1) // Some(DayOfWeek(1))
DayOfWeek.from(7) // Some(DayOfWeek(7))
DayOfWeek.from(8) // None
Opaque Type Aliases
Opaque types aliases provide type abstraction without any overhead. Opaque types can be enhanced
with through extension methods. Here, Inside object BankingMoney, Money is a BigDecimal.
Outside, it is a new type with only the method to. Inside BankingBalance, Balance is a BigDecimal.
This allows the representation of a Balance remaining a Balance even if adding or subtracting
Money. Additionally extension methods can provide smart constructors.
object BankingMoney:
 opaque type Money = BigDecimal
 object Money:
 def from(bi: BigDecimal): Money = bi
 extension (b: Money)
 def to: BigDecimal = b
object BankingBalance:
 import BankingMoney.Money
 
 opaque type Balance= BigDecimal
 
 object Balance:
 def from(bi: BigDecimal): Balance = bi
 
 extension (b: Balance)
 def to: BigDecimal = b 
 def + (m: Money): Balance = b + m.to
 def - (m: Money): Balance = b - m.to
Exercises
1. Implement the Student case class, in project lab04, with attributes firstName and
lastName, which consists only of letters, and age, which must be greater than zero. Create
a smart constructor which does not allow values that do not belong to the domain. Provide
an auxiliary form of construction that accepts a long name such as “Ana Júlia Silva” and an
age. The implementation should pass the tests.
2. Implement opaque types StringWithOnlyLeters, StringWithLettersAndSpaces
and PositiveInteger. These types should be defined in the SimpleTypes object. The
implementation should pass the tests.
3. Implement the OtherStudent case class, similar to the Student class, but using the
opaque types for StringWithOnlyLeters, StringWithLettersAndSpaces and
PositiveInteger. The implementation should pass the tests.
	Traits
	Case Classes
	Exercises
	Objects
	Singleton Objects
	Companion Objects
	Smart Constructors
	Opaque Type Aliases
	Exercises

Continue navegando