서론
C언어 처음 배울때 과제에서 리스트, 스택, 큐, 트리 등의 자료구조를 구현하는 과제를 많이 했었습니다. Scala에서는 그런 컬랙션들을 포함한 Java에서 객체가 아닌 프라이머리 타입들(Int, Char, Byte, Long, Double, Float, …) 까지 전부 객체입니다. 이 스칼라라는 언어가 참 묘한게 모든 타입은 객체면 그냥 객체지향이겠지만 함수까지 객체 취급을 해줘서 함수를 객체나 함수의 인자로 넘겨주거나 돌려주는게 가능합니다.
이 글에서는 이러한 함수형과 객체지향의 특징 몇 개를 살펴보고 Scala의 대략적인 타입 구조를 살펴 보겠습니다.
컬랙션에 관해서는 내용이 방대해서 다음 글에서 다루도록 하겠습니다.
함수도 객체 취급해주는 함수형
적어도 Scala는 Java 보다 휠씬 객체지향에 가깝습니다. 인터페이스, 제네릭 같은 문법을 전부 빼놔도 타입시스템만 봐도 Java는 Int, Char 같은 타입은 객체가 아닌 반면 Scala에서는 모든게 객체입니다.
여기서 끝나면 그냥 스몰토크처럼 완벽한 객체지향에 근접한 언어겠지만 함수도 객체 취급해서 함수를 인자로 넘기거나 받는게 가능합니다. 이런 점 때문에 Scala
는 함수형+객체지향의 특징을 둘 다 가진 하이브리드 언어입니다.
함수를 인자로 넘기는 커링(curring)
/** 인자로 받은 함수를 Try로 감싸서 실행
* @param num Int형의 두번째 인자...
* @param A Int를 인자로 받아 Double을 돌려주는 함수 인자
*/
def haskell(A: Int => Double)(num: Int) : Try[Double] = {
Try {
A(num)
}
}
haskell(a => a / 10)(0) // return Try Fail
haskell(a => a / 10)(30) // return 3
커링에 관해선 나중에 따로 시간을 할애해서 글을 올리겠습니다.
조금 더 알아보는 함수형 특징
함수를 객체처럼 사용하는 것 이외에 몇 가지 재미있는 점이 있습니다. C++에서는 연산자를 자기 멋대로 재정의 하는 연산자 오버로딩
이 가능합니다. Scala에서도 가능합니다. 그때 그 논리가 나름 재미있습니다.
Scala
에서는 연산자도 함수입니다. 그래서 다음 예시처럼 기괴한 연산이 가능합니다.
val a= 8
val b= 2
a.+(8)
b.*(a)
이런 점을 이용해 연산자를 오버로딩 할 수 있습니다. 한가지 끔찍한 점은 연산자를 오버로딩 하면서 엉뚱한 동작으로 할 수 있다는 것 입니다.
def + (m: Me) = {
getData(this.data + m.data)
println(this.data) //엉뚱한 동작
}
//장난질
def / (m: Me) = {
getData(this.data * m.data)
}
타입시스템
출처: https://github.com/wonury/Programming.In.Scala/wiki/Chapter-11.
원래는 코세라 스칼라에 있는 이미지를 퍼왔습니니다.
스칼라의 타입은 위의 이미지 대로 Any
에서 시작해서 갈라져 나왔습니다. 왼쪽의 AnyVal
을 상속한 타입들은 Java에서는 객체가 아니었던 타입들이고 오른 쪽의 AnyRef
를 상속한 객체들은 Object
를 상속 받는 컬랙션들이 주를 이룹니다.
모든 클래스가 Any
에서 나왔기에 서로 동등 비교가 가능합니다.
원시 타입은 없다
보이는 바와 같이 원시 타입은 없고 전부 객체입니다. 이미지를 보시면 view라는 화살표로 이어져있는데. 상속관계가 없어도 타입 간의 암시적 변환을 나타내줍니다.
class object 차이
이런 타입 시스템과 별개로 Scala
로 코딩할때는 Object와 Class라는 키워드로 클래스를 만듬니다.
Object
는 싱글턴 객체를 만드는 키워드 입니다.
Class
는 평범한 Class를 만드는 키워드 입니다.
싱글톤
스칼라에서는 class대신 object 라는 키워드로 싱글턴을 만들수 있습니다. 한 파일 안에서 클래스 이름과 같은 싱글톤(object)를 만들면 이를 동반 객체 companion object 라고 부르고 클래스를 동반 클래스 companion class라고 부른다. 클래스와 동반 객체는 상대방의 비공개(private) 맴버에 접근할수 있습니다.
동반 클래스가 없는 싱글톤을 독립 객체라고 합니다. 도구 메소드를 모아두거나 스칼라 어플리케이션의 진입점으로 만들때 사용할수 있습니다.
object test{
def main(args: Array[String]) = {
}
}