3. Inheritance
Inheritance is a way by which an object of a class acquire properties
and behavior of object of other class.
So Inheritance is used for code reuse.
In Scala we use “extends” keyword to inherit properties and behavior
extends
from a class.This is same as Java
class Animal
class Bird extends Animal
Omitting extends means extends AnyRef
4. Calling superclass constructor
Subclasses must immediately call their superclass constructor
scala> class Animal(val name: String)
defined class Animal
scala> class Bird(name: String) extends Animal(name)
defined class Bird
5. Use the keyword final to prevent a
class from being subclassed
Scala> final class Animal
defined class Animal
Scala> class Bird extends Animal
<console>:8: error: illegal inheritance from final class Animal
6. Use the keyword sealed to allow
sub-classing only within the
same source file
sealed class Animal
class Bird extends Animal
class Fish extends Animal
This means, that sealed classes can only be subclassed by you
but not by others, i.e. you know all subclasses
7. Use the keyword override to
override a superclass member
class Animal {
val name = "Animal"
}
class Bird extends Animal {
override val name = "Bird"
}
8. Abstract classes
Use the keyword abstract to define an abstract class
abstract class Animal {
val name: String
def hello: String
}
9. Implementing abstract members
Initialize or implement an abstract field or method to make it
Concrete
class Bird(override val name: String) extends Animal {
override def hello = "Beep"
}
10. Traits
Traits are like Interfaces but they are richer than Java
Interfaces
They are fundamental unit of code reuse in Scala
They encapsulates method and field definitions, which can
be reused by mixing them in classes
Unlike class inheritance a class can mix any number of traits
Unlike Interfaces they can have concrete methods
11. Unlike Java interfaces traits can
explicitly inherit from a class
class A
trait B extends A
12. Mix-In Compotition
One major use of traits is to automatically add methods to
class in terms of methods the class already has. That is, trait
can enrich a thin interface,making it into a rich interface.
trait Swimmer {
def swim() {
println("I swim!")
}
}
Use the keyword with to mix a trait into a class that already
extends another class
class Fish(val name: String) extends Animal with Swimmer
So method swim can mix into class Fish ,class Fish does not
need to implement it.
13. Mixing-in multiple traits
Use the keyword with repeatedly to mix-in multiple traits
Trait A
Trait B
Trait C
Class D extends A with B with C
If multiple traits define the same members, the outermost
(rightmost) one “wins”
14. Ordered Trait
When-ever you compare two objects that are ordered, it is
convenient if you use a single method call to ask about the
precise comparison you want.
if you want “is less than,” you would like to call <
if you want “is less than or equal,” you would like to call <=
A rich interface would provide you with all of
the usual comparison operators, thus allowing you to
directly write things
like “x <= y”.
15. Ordered Trait
We have a class Number
class Number(a:Int) {
val number =a
def < (that: Number) =this.number < that.number
def > (that: Number) = this.number > that.number
def <= (that: Number) = (this < that) || (this == that)
def >= (that: Number) = (this > that) || (this == that)
}
16. Ordered Trait
We have a class Number which extends ordered trait
class Number(a:Int) extends Ordered[Number] {
val number=a
def compare(that:Number)={this.number-that.number}
}
So compare method provide us all comparison
operators
17. Traits as stackable modifications
Traits let you modify the methods of a class, and they do
so in a way that allows you to stack those modifications with each other.
Given a class that implements such a queue, you could define traits to
perform modifications such as these
Doubling: double all integers that are put in the queue
Incrementing: increment all integers that are put in the queue
Filtering: filter out negative integers from a queue
18. Traits as stackable modifications
abstract class IntQueue {
def get(): Int
def put(x: Int)
}
class BasicIntQueue extends IntQueue {
private val buf = new ArrayBuffer[Int]
def get() = buf.remove(0)
def put(x: Int) { buf += x }
}
19. Traits as stackable modifications
val queue = new BasicIntQueue
queue.put(10)
queue.put(20)
queue.get() it will return 10
Queue.get() it will return 20
20. Traits as stackable modifications
take a look at using traits to modify this behavior
trait Doubling extends IntQueue {
abstract override def put(x: Int) { super.put(2 * x) }
}
class MyQueue extends BasicIntQueue with Doubling
val queue = new MyQueue
queue.put(10)
queue.get() it will return 20
22. Traits as stackable modifications
take a look at using traits to modify this behavior
val queue = (new MyQueue extends BasicIntQueue with Doubling
with Incrementing with Filtering)
queue.put(-1); queue.put(0); queue.put(1)
queue.get()
Int = 2 Filtering
Increamenting
Doubling
23. Option Type
Scala has a standard type named Option for optional
values. Such a value can be of two forms. It can be of the
form Some(x) where x is the actual value. Or it can be
the None object, which represents a missing value
24. Option Pattern
object OptionPatternApp extends App {
val result = divide(2, 0).getOrElse(0)
println(result)
def divide(x: Double, y: Double): Option[Double] = {
try {
Option(errorProneMethod(x, y))
} catch {
case ex => None
}
}
def errorProneMethod(x: Double, y: Double): Double = {
if (y == 0) throw new Exception else {x / y}
}
}