2015. 4. 19. 14:44ㆍProgramming/Scala
이번에는 분수를 저장할 수 있는 클래스를 스칼라를 이용하여 만들어 볼 것이다.
기본 definition은 아래와 같다.
class Rational(n:Int, d:Int)
n에 분자가 d에 분모 값을 파라미터로 하는 class를 생성하였다. Java와의 다른 점인데 scala에서는 따로 생성자 함수를 만들지 않고 class에서 파라미터를 받고 처리하도록 되어 있다.
클래스를 만들었으니 한번 생성해보자.
생성은 무사히 잘된 것 같은데 밑에 이상한 글씨들이 뜬다.. toString을 기본적으로 overriding 해주지 않으면 default로 클래스 이름@16진수 이런식의 어떤 값을 표시해 줄 것이다. 좀 더 명확히 하기 위해 toString을 재정의해주자.
class Rational(n:Int, d:Int){
val numer: Int = n
val denom: Int = d
override def toString = numer + "/" + denom
}
이렇게 한 후 다시 아래와 같이 Rational을 생성해보자.
분모에 0이 들어가는 경우는 어떨까?
원래 분모에 0이 들어가게 되면 Rational 객체를 아예 생성을 하면 안되어야 한다. 그 구문을 추가해보자.
class Rational(n:Int, d:Int){
require(d != 0)
val numer: Int = n
val denom: Int = d
override def toString = numer + "/" + denom
}
require란 함수는 해당 조건이 만족할때만 그 아래의 코드들을 실행시킨다. 만약 해당 조건을 만족시키지 못하면 에러를 리턴하고 객체 생성은 중지된다.
그런데 객체를 생성할 때 파라미터 값을 다르게 주고 싶으면 어떻게 해야 할까? 자바나 C++ 같은 경우에는 생성자 overloading이라고 해서 여러번 정의를 할 수가 있었는데...
그러고 보니 스칼라에서는 기본 생성자도 보이지 않는다.
스칼라에서는 위의 형태처럼 class에서 파라미터 값을 받으면 인터프리터에서 주 생성자를 만드는 형태로 되어 있다. 그래서 따로 생성자를 만들지 않아도 생성자가 호출이 된다.
그럼 생성자를 여러개 만들고 싶을때는 어떻게 해야할까??
class Rational(n:Int, d:Int){
require(d != 0)
val numer: Int = n
val denom: Int = d
def this(n: Int) = this(n, 1)
override def toString = numer + "/" + denom
}
보조 생성자를 만들고 싶다면 def this(..) 형태로 작성을 하면 스칼라에서는 보조 생성자로 인식한다. 보조 생성자에서는 반드시 주 생성자를 호출해야 코드로 시작해야 원할하게 동작한다. 즉 모든 보조 생성자의 시작은 this(...)로 시작해야 한다.
이제 거의 다 만들어졌다. 이번에는 분수 간의 덧셈 연산자 처리를 해보자.
class Rational(n:Int, d:Int){
require(d != 0)
val numer: Int = n
val denom: Int = d
def this(n: Int) = this(n,1)
override def toString = numer + "/" + denom
def + (obj: Rational): Rational = new Rational(numer * obj.denom + obj.numer * denom, denom * obj.denom)
def + (i: Int): Rational = new Rational(numer + i * denom, denom)
+ 매서드 뒤에 Rational 객체를 받는 경우와 정수를 받는 경우에 대해 각각 overloading하였다.
만약에 3 + x를 하면 어떻게 될까? + 는 Rational에 대한 매서드이지, 3이란 정수에 대한 매서드가 아니기 때문에 분명 오류를 낼 것이다.
스칼라에는 암시적 변환이란게 있다. implicit라는 키워드는 스칼라 인터프리터에게 '어떤 상황에 대해서는 해당 메소드처럼 변환해라' 라고 정의를 내려 준다.
지금은 'int에 대해 Rational로 객체로 변환해라' 라고 인터프리터에게 알려주었고, 인터프리터는 이를 받아들여 int가 들어오면 이를 Rational 객체로 암시적 변환을 한다.
위 선언은 스코프 범위가 있으며 범위를 벗어날 경우에는 해당 규칙이 적용되지 않는다.