【2019-05-23】特質trait
7261 ワード
特質はScalaのコード多重化の基礎ユニットである.特質はメソッドとフィールドの定義をカプセル化し、クラスに混入して再利用することができます.特質の定義はキーワードtraitを用いる以外はクラス定義と変わらない.
extendsを用いて特質を混入する
使用with混入特質
複数の特質を混入する
痩せインタフェース対肥満インタフェースの特質の1つの主要な応用方式はクラスの既存の方法によって自動的にクラスに方法を追加することができて、すなわち:特質は1つのやせインタフェースを豊かにすることができて、それを太ったインタフェースに変えることができます.
長方形オブジェクト
ordered特質
特質は積み重ね可能な変更に用いられる
trait Philosophical {
def philosophize() {
println("I consume memory, therefore I am!")
}
}
extendsを用いて特質を混入する
class Frog extends Philosophical {
override def toString = "green"
}
//Frog AnyRef(Philosophical ) Philosophical
//
val frog=new Frog
//frog: Frog = green
//Phil Philosophical, , Phil Philosophical
val phil:Philosophical=frog
//phil: Philosophical = green
frog.philosophize()
//I consume memory, therefore I am!
使用with混入特質
object Ex1 {
class Animal
class Frog extends Animal with Philosophical {
override def toString = "green"
}
def main(args: Array[String]) {
println("new Frog [" + (new Frog) + "]")
}
}
複数の特質を混入する
class Animal
trait HasLegs
class Frog extends Animal with Philosophical with HasLegs {
override def toString = "green"
}
痩せインタフェース対肥満インタフェースの特質の1つの主要な応用方式はクラスの既存の方法によって自動的にクラスに方法を追加することができて、すなわち:特質は1つのやせインタフェースを豊かにすることができて、それを太ったインタフェースに変えることができます.
object Ex2 {
class Animal
class Frog extends Animal with Philosophical {
override def toString = "green"
override def philosophize() {
println("It ain't easy being "+ toString +"!")
}
}
class Point(x: Int, y: Int)
trait CharSequence {
def charAt(index: Int): Char
def length: Int
def subSequence(start: Int, end: Int): CharSequence
def toString(): String
}
trait Ordered[T] {
def compare(that: T): Int
def (that: T): Boolean = (this compare that) > 0
def <=(that: T): Boolean = (this compare that) <= 0
def >=(that: T): Boolean = (this compare that) >= 0
}
import scala.collection.mutable.ArrayBuffer
class BasicIntQueue extends IntQueue {
private val buf = new ArrayBuffer[Int]
def get() = buf.remove(0)
def put(x: Int) { buf += x }
}
trait Incrementing extends IntQueue {
abstract override def put(x: Int) { super.put(x + 1) }
}
trait Doubling extends IntQueue {
abstract override def put(x: Int) { super.put(2 * x) }
}
def main(args: Array[String]) {
(new Frog).philosophize()
// Multiple inheritance thought experiment
val q = new BasicIntQueue with Incrementing with Doubling
q.put(42) // which put would be called?
println("q [" + q + "]")
}
}
長方形オブジェクト
class Point(val x: Int, val y: Int)
class Rectangle(val topLeft: Point, val bottomRight: Point) {
def left = topLeft.x
def right = bottomRight.x
def width = right - left
}
abstract class Component {
def topLeft: Point
def bottomRight: Point
def left = topLeft.x
def right = bottomRight.x
def width = right - left
}
trait Rectangular {
def topLeft: Point
def bottomRight: Point
def left = topLeft.x
def right = bottomRight.x
def width = right - left
}
class Rectangle(val topLeft: Point, val bottomRight: Point)
extends Rectangular {
}
val rect = new Rectangle(new Point(1, 1),new Point(10, 10))
//rect: Rectangle = Rectangle@5128197f
rect.left
//res2: Int = 1
rect.right
//res3: Int = 10
rect.width
//res4: Int = 9
ordered特質
// ,4 、<=、>=
class Rational(n: Int, d: Int) {
def < (that: Rational) =
this.numer * that.denom > that.numer * this.denom
def > (that: Rational) = that < this
def <= (that: Rational) = (this < that) || (this == that)
def >= (that: Rational) = (this > that) || (this == that)
}
// ordered Rational
// compare ,ordered 、<=、>=
class Rational(n: Int, d: Int) extends Ordered[Rational] {
def compare(that: Rational) =
(this.numer * that.denom) - (that.numer * this.denom)
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
def + (that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
def + (i: Int): Rational =
new Rational(numer + i * denom, denom)
def - (that: Rational): Rational =
new Rational(
numer * that.denom - that.numer * denom,
denom * that.denom
)
def - (i: Int): Rational =
new Rational(numer - i * denom, denom)
def * (that: Rational): Rational =
new Rational(numer * that.numer, denom * that.denom)
def * (i: Int): Rational =
new Rational(numer * i, denom)
def / (that: Rational): Rational =
new Rational(numer * that.denom, denom * that.numer)
def / (i: Int): Rational =
new Rational(numer, denom * i)
override def toString = numer +"/"+ denom
private def gcd(a: Int, b: Int): Int =
if (b == 0) a else gcd(b, a % b)
override def equals(other: Any): Boolean =
other match {
case that: Rational =>
(that canEqual this) &&
numer == that.numer &&
denom == that.denom
case _ => false
}
def canEqual(other: Any): Boolean =
other.isInstanceOf[Rational]
override def hashCode: Int =
41 * (
41 + numer
) + denom
}
特質は積み重ね可能な変更に用いられる
//IntQueue put , get
abstract class IntQueue {
def get(): Int
def put(x: Int)
}
object Ex2 {
class Animal
class Frog extends Animal with Philosophical {
override def toString = "green"
override def philosophize() {
println("It ain't easy being "+ toString +"!")
}
}
class Point(x: Int, y: Int)
trait CharSequence {
def charAt(index: Int): Char
def length: Int
def subSequence(start: Int, end: Int): CharSequence
def toString(): String
}
trait Ordered[T] {
def compare(that: T): Int
def (that: T): Boolean = (this compare that) > 0
def <=(that: T): Boolean = (this compare that) <= 0
def >=(that: T): Boolean = (this compare that) >= 0
}
import scala.collection.mutable.ArrayBuffer
// ArrayBuffer BasicIntQueue
class BasicIntQueue extends IntQueue {
private val buf = new ArrayBuffer[Int]
def get() = buf.remove(0)
def put(x: Int) { buf += x }
}
val queue = new BasicIntQueue
//queue: BasicIntQueue = BasicIntQueue@3e1c58c9
queue.put(10)
queue.put(20)
queue.get()
//res17: Int = 10
queue.get()
//res18: Int = 20
// Incrementing Filtering
trait Incrementing extends IntQueue {
abstract override def put(x: Int) { super.put(x + 1) }
}
trait Filtering extends IntQueue {
abstract override def put(x: Int) {
if (x >= 0) super.put(x)
}
}
//
//Doubling
trait Doubling extends IntQueue {
abstract override def put(x: Int) { super.put(2 * x) }
}
def main(args: Array[String]) {
(new Frog).philosophize()
//
val q = new BasicIntQueue with Incrementing with Doubling
q.put(42) // put
println("q [" + q + "]")
}
}