Base : Interface
Core : Functionality (trait or concrete class)
Custom : Modifications
Stack 구현하기
1. BASE
trait Stack[A] {
def get():(A,Stack[A])
def put(x:A):Stack[A]
}
2. CORE
피자에 해당
class BasicIntStack protected (xs: List[Int]) extends Stack[Int]
{
override val toString = "Stack:" + xs.toString
def this() = this(Nil) //empty stack
protected def mkStack(xs: List[Int]): Stack[Int] = new BasicIntStack(xs)
def get(): (Int,Stack[Int]) = (xs.head, mkStack(xs.tail))
def put(x: Int): Stack[Int] = mkStack(x :: xs)
}
val s0 = new BasicIntStack val s1 = s0.put(3)
val s2 = s1.put(-2)
val s3 = s2.put(4)
val (v1,s4) = s3.get() //(4,(-2,3))
val (v2,s5) = s4.get() //(-2,3)
Q. 왜 mkStack으로 했을까?
-> type class와 연관되는 질문
-> 이렇게 안하면 mixin을 할 때 문제가 생김
-> mkStack을 override 할 수 있음.
3. CUSTOM
trait Doubling extends Stack[Int] {
abstract override def put(x: Int): Stack[Int] = super.put(2 * x)
}
//triat는 new를 못함.ONLY class만
//super가 나타내는것? --> 내 부모, stack의 함수 (stack.put)
//근데 super인 stack에 구현이 없음 --> 그래서 abstract를 앞에 붙인것.
// abstract와 함께 쓰이는 super는 의미가 조금 다름.
trait Incrementing extends Stack[Int] {
abstract override def put(x: Int): Stack[Int] = super.put(x + 1)
}
trait Filtering extends Stack[Int] {
abstract override def put(x: Int): Stack[Int] =
if (x >= 0) super.put(x) else this
}
Q. abstract override super의 의미?
-> 부모는 아님. 부모에 구현이 없는 경우에도 사용해야 하기 때문에.
-> put이 만들어진 역사 중 가장 최근에 정의된 put을 사용함. (전 수업에 부모에 떡 돌린 예시 있잖. 한 클래스당 한 번 방문)
4. Stacking
class DIFIntStack protected (xs: List[Int]) extends BasicIntStack(xs)
with Doubling with Incrementing with Filtering
{
def this() = this(Nil)
override def mkStack(xs: List[Int]): Stack[Int] = new DIFIntStack(xs)
}
val s0 = new DIFIntStack
val s1 = s0.put(3)
val s2 = s1.put(-2)
val s3 = s2.put(4)
val (v1,s4) = s3.get()
val (v2,s5) = s4.get()
'프로그래밍 > Scala' 카테고리의 다른 글
Scala Array 문법 (0) | 2022.11.22 |
---|---|
Scala String 문법 (0) | 2022.11.22 |
1101 Inheritance vs. Composition (0) | 2022.11.01 |
Structure Type (0) | 2022.10.21 |
Currying & Closure 완전 이해하기 (0) | 2022.10.21 |