KoreanFoodie's Study

Scala 10 - Class 본문

Tutorials/Scala

Scala 10 - Class

GoldGiver 2019. 4. 23. 19:08

스칼라 튜토리얼, scala의 class에 대해 알아보자


Class: Parameterized Record

object gee {
    val a : Int = 10
    def b : Int = a + 20
    def f(z: Int) : Int = b + 20 + z
}
type gee_type = {val a:Int; def b: Int; def f(z:Int): Int}

class foo_type(x: Int, y: Int) {
    val a : Int = x
    def b : Int = a + y
    def f(z: Int) : Int = b + y + z
}
val foo : foo_type = new foo_type(10,20)

If you define class, new type is made. The name really matters.

  • use: foo.a foo.b foo.f
  • foo is a value of foo_type
  • gee is a value of gee_type

Class: No Structural Sub Typing

  • Records: Structural sub-typing
foo_type <: gee_type
  • Classes: Nominal sub-typing
gee_type <: foo_type
val v1: gee_type = foo
val v2: foo_type = gee     // type error. WHY?

There's something special about class... The secret is Recursion!


Class: Can be Recursive!

class MyList[A](v: A, nxt: Option[MyList[A]]) {
    val value: A = v
    val next: Option[MyList[A]] = nxt
}
type YourList[A] = Option[MyList[A]]

val t: YourList[Int] =
    Some(new MyList(3, Some(new MyList(4, None))))

Note on Null value

  • null : The special element of every class & structural type

This value is needed to construct disjoint union types using classes in Java, which, however, is not as elegant and type safe as algebraic data types(ADTs):

  1. Such disjoint union types can contain junk values (not elegant).

  2. Null-point exception can be raised at run time (not type safe).

For this reason, it is discouraged to use null in Scala although Scala supports null for compatibility with Java.

Instead, it is encouraged to use ADTs, which themselves are classes and thus take advantages of both ADT and class.


Simplification using Argument Members

class MyList[A](v: A, nxt: Option[MyList[A]]) {
    val value = v
    val next = nxt
}

class MyList[A](val value: A, val next: Option[MyList[A]]) {

}

class MyList[A](val value: A, val next: Option[MyList[A]])

Type does not tell you it includes null or not. Therefore it may cause run time error if you try to put value on null type.


Simplification using Companion Object

class MyList[A](v: A, nxt: Option[MyList[A]]) {
  val value = v
  val next = nxt
}

object MyList { // val MyList = new
  def apply[A](v: A, nxt: Option[MyList[A]]) =
    new MyList(v, nxt) // This creating MyList "class"
} // This is purely record type!

type YourList[A] = Option[MyList[A]]

val t0 = None
val t1 = Some(new MyList(3, Some(new MyList(4, None))))
val t2 = Some(MyList(3, Some(MyList(4, None))))        
// Without new, It tries to find Object, not class!

Last two sentences are actually the same!

  • Exercise :

Define a class "MyTree[A]" for binary trees:

MyTree[A] =
(value: A)*
(left: Option[MyTree[A]]) *
(right: Option[MyTree[A]])

  • Solution :
class MyTree[A](v: A,
                lt: Option[MyTree[A]],
                rt: Option[MyTree[A]]) {
  val value = v
  val left = lt
  val right = rt
}

type YourTree[A] = Option[MyTree[A]]

val t0 : YourTree[Int] = None
val t1 : YourTree[Int] = Some(new MyTree(3, None, None))
val t2 : YourTree[Int] =
  Some(new MyTree(3, Some (new MyTree(4,None,None)), None))

Nominal Sub Typing for Classes

  • Nominal Sub Typing, a.k.a Inheritance
class foo_type(x: Int, y: Int) {
  val a: Int = x
  def b: Int = a + y
  def f(z: Int): Int = b + y + z
}

class gee_type(x: Int) extends foo_type(x+1, x+2) {
  val c: Int = f(x) +b
}

// gee_type <: foo_type

(new gee_type(30)).c             // 188
def test(f: foo_type) = f.a + f.b

test(new foo_type(10,20))        // 40
test(new gee_type(30))            // 94

Overriding 1

class foo_type(x: Int, y: Int) {
  val a: Int = x
  def b: Int = a + y
  def f(z: Int): Int = b + y + z
}

class gee_type(x: Int) extends foo_type(x+1, x+2) {
  override def f(z: Int) = b + z
  // or, override def f(z: Int) = super.f(z) * 2
  val c: Int = f(x) +b
}

// gee_type <: foo_type

(new gee_type(30)).c

override def f(z: String): Int = 77        //No, arg: diff type
def f(z: String): Int = 77                 //Yes, arg: diff type
override def f(z: Int): Nothing = ???     //Yes, ret: sub type

Overriding 2

class foo_type(x: Int, y: Int) {
    val a : Int = x
    def b : Int = a + y
    def f(z: Int) : Int = b + y + z
}

class gee_type(x: Int) extends foo_type(x+1,x+2) {
    override def b = 10 
}

(new gee_type(30)).f(0)        // 42

Example: My List

class MyList[A]()
class MyNil[A]() extends MyList[A]
class MyCons[A](val hd: A, val tl: MyList[A]) 
  extends MyList[A]
val t: MyList[Int] = 
  new MyCons(3, (new MyCons(4, new MyNil())))

Example: MyList

class MyList[A]

class MyNil[A]() extends MyList[A]
object MyNil { def apply[A]() = new MyNil[A]() }

class MyCons[A](val hd: A, val tl: MyList[A]) 
  extends MyList[A]
object MyCons {
  def apply[A](hd:A, tl:MyList[A]) = new MyCons[A](hd, tl)}

val t: MyList[Int] = MyCons(3, MyNil())

def length(x: MyList[Int]) = ???

Case Class

class MyList[A]() { … }

case class MyNil[A]() extends MyList[A] { … }
//object MyNil { def apply[A]() = new MyNil[A]() }

case class MyCons[A](hd: A, tl: MyList[A]) 
extends MyList[A] { … }
//object MyCons {
//  def apply[A](hd:A, tl:MyList[A]) = new MyCons[A](hd, tl)}

val t: MyList[Int] = MyCons(3, MyNil())

//  + Pattern Matching
//  Cf. sealed abstract class MyList[A]

Excercise

Define "MyTree[A]" using sub class.

class MyTree[A](v: A,
                lt: Option[MyTree[A]],
                rt: Option[MyTree[A]]) {
  val value = v
  val left = lt
  val right = rt
}

type YourTree[A] = Option[MyTree[A]]

Solution

sealed abstract class MyTree[A]
case class Empty[A]() extends MyTree[A]
case class Node[A](value: A,
                   left: MyTree[A],
                   right: MyTree[A])
  extends MyTree[A]

val t : MyTree[Int] =
  Node(3, Node(4,Empty(),Empty()), Empty())

t match {
  case Empty() => 0
  case Node(v,l,r) => v
}

'Tutorials > Scala' 카테고리의 다른 글

Scala 11 - Abstract Class, Basics  (0) 2019.04.24
Scala 9 - Sub Types  (0) 2019.04.23
Scala 8 - Parametric Polymorphism  (0) 2019.04.23
Scala 7 - Datatypes2  (0) 2019.04.23
Scala 6 - Datatypes  (0) 2019.04.23
Comments