스칼라의 기본 타입은 자바와 동일하게 byte short int 등이 있습니다. 이들의 숫자 범위도 자바와 동일합니다.

자바와 다른 점은 기본 타입이 클래스로 정의되어 있다는 점입니다.

여기서 보이는 기본 타입은 모두 scala라는 패키지 내부에 잇고 Striingjava lang패키지 안에 있는 것을 사용합니다.

스칼라는 자동으로 scalajava.lang 패키지를 import 하기 때문에 저희는 어떠한 import 구문 없이 기본형 타입과 String을 사용할 수 있습니다.

또한 스칼라와 자바 기본 타입 범위가 같기 때문에 스칼라 컴파일러는 기본 타입을 자유롭게 자바의 primitive 타입으로 변환 가능합니다.

 

리터럴은 상수 값을 코드에 직접 적는 것을 의미합니다.

정수 리터럴로는 Int, Long, Short, Byte가 있으며 스칼라는 10진수, 16진수를 표현할 수 있습니다. 16진수를 표현하려면 값 앞에 “0x”를 붙이면 됩니다.

정수 값 뒤에 L이나 l을 붙이면 Long 타입이 되고 아무 것도 없으면 Int 형이 됩니다. , 숫자 값은 디폴트로 Int형을 나타내고 위 코드와 같이 변수 선언 시 Short로 명시하면 Int형인 숫자는 Short 형으로 바뀝니다.

부동 소수점 리터럴은 Float, Double이 있으며 지수 부분은 “e”로 표현하는 데 10의 제곱승을 의미합니다. 값 뒤에 Ff를 붙이면 Float형이 되고 아무것도 없으면 Double 형이 됩니다.

문자 리터럴은 작은 따옴표로 둘러싼 문자로 표현합니다. 큰 따옴표로 둘러쌀 경우 String 타입이 됩니다. 문자 값은 “\u” 붙여 유니코드 형식으로 표현가능합니다.

또한 자바와 비슷하게 특수 문자를 ‘\’ 통해 표현할 수 있습니다.

문자열 리터럴은 String 타입 상수를 의미하며 대괄호로 둘러싸면 됩니다. 스칼라의 문자열 리터럴 중 독특한 Raw 문자열이라는 개념이 있습니다. 

기존에 특수문자, 따옴표, 개행문자는 “\”를 앞에 붙여서 넣을 수 있는 데 Raw 문자열을 사용하면 “\” 없이 개행 문자, 따옴표, 특수 문자 없이 타이핑한 문자열 그대로 표현 가능합니다.

Raw 문자열을 사용하려면 큰 따옴표 세 개로 둘러쌓으면 됩니다.  그러면 왼쪽 코드와 같이 큰 따옴표와 개행이 “\”없이 그대로 이루어 진 것을 볼 수 있습니다.

, “Type” 문자열 앞에 띄어쓰기도 그대로 표현하는 데 이 띄어쓰기를 조절해주려면 오른쪽과 같이 “|”를 넣어주면 됩니다.  그러면 해당 줄의 띄어쓰기가 “|” 기준 뒤부터 적용됩니다.

 

 

심볼 리터럴은 작음 따옴표 뒤에 알파벳과 숫자를 혼합한 식별자로 표현합니다.

아래 코드와 같이 a라는 변수에 “’hi” 심볼 리터럴을 넣어주면 스칼라 컴파일러는 ‘hi 심볼에 대해 Symbol(“hi”) 팩토리 메소드를 호출해 a 변수에 Symbol 인스턴스를 매핑해줍니다.

또한 동일한 식별자를 가진 심볼 리터럴은 동일한 Symbol 객체를 참조하게 됩니다. 아래 코드와 같이 ab가 같은 객체를 참조하는 것을 볼 수 있습니다.

 

문자열 인퍼폴레이션을 이용하면 문자열 리터럴 내부에 표현식을 내장해 문자열을 가독성 있게 표현 가능합니다.

S 문자열 인퍼폴레이션은 내장된 각 표현식을 평가/계산하고 toString으로 대치시킵니다. 각 표현식 앞에는 “$”를 붙어야 합니다.

코드를 보면 println 내부에 s를 붙이고 문자열을 입력합니다. 그러면 스칼라 컴파일러에서 s 문자열 인퍼폴레이션으로 인식하고 $ 뒤에 붙은 표현식을 찾아 표현식을 평가한 후 toString을 호출합니다.

그래서 최종적으로 “Hello, reader!” 가 출력됩니다.

S 문자열 인터폴레이션에서 $ 뒤에 오는 표현식이 변수 하나라면 변수 이름만 적으면 되지만 그 외의 경우에는 중괄호로 묶어서 하나의 표현식이라는 것을 알려줘야 합니다.

Raw 문자열 인터폴레이션은 s와 동일하게 동작하고 문자열 이스케이프 시퀀스를 인식하지 않습니다.

F 문자열 인터폴레이션 또한 s와 동일하고 추가적으로 printf 스타일 형식 지정이 가능합니다.

이 문자열 인터폴레이션은 컴파일 시점에 코드를 재작성하는 형태로 구현되어 있고 컴파일러에서 식별자 바로 뒤에 문자열 리터럴이 오면 인터폴레이터로 취급하게 되어 있고 s, f, raw 처럼 커스텀하게 구현도 가능합니다.

 

 

스칼라에서 모든 연산자는 메소드입니다.

1+21 객체의 + 메소드를 호출한 것으로 + 메소드는 2라는 Int 형 객체를 파라미터를 받는 것과 같습니다.

이렇게 2라는 Int 형 객체를 파라미터로 받을 수 있는 것은 Int 클래스 내부에 Int형 인자를 받는 + 메소드가 정의되어 있기 때문입니다.

따라서 1+2 뿐만 아니라 1+2.0 또는 1+ 2L 과 같이 다른 타입의 리터럴에 대해 더하기를 하려면 해당 타입의 리터럴을 인자로 받는 메소드가 존재해야 합니다.

, Int 클래스에는 파라미터 타입에 따라 오버로드한 + 메소드가 여러 개 존재하게 됩니다. 그래서 1+2L도 가능합니다.

+라는 메소드를 일반적으로 생각해 보면 파라미터가 있는 메소드는 중위연산자처럼 표현가능 하다고 할 수 있습니다.

코드와 같이 indexOf 라는 하나의 파라미터를 받는 메서드는 중위 연산자 처럼 사용할 수 있습니다. 또한 여러 인자를 받는 다면 괄호로 묶어줍니다.

 

전위 연산자는 “unary_연산자" 메소드로 변경 가능합니다. 그래서 ! 연산자는 unary_! 되겠습니다. 만약 커스텀하게 연산자를 만들고 싶다면 unary_연산자 이름으로 메소드를 정의하면 됩니다.

인자를 취하지 않는 메소드는 후위 연산자처럼 사용가능 합니다.

코드를 보면 toLowerCases toLowerCase로 바꿀 수 있습니다.

 

두 객체가 같은 지 비교할 때는 “==“을 사용합니다. “==“연산자는 단순히 객체의 주소를 비교하는 지 않습니다.

동작 방식을 살펴보면 좌항이 null 인지 검사하고 null 이 아니라면 해당 객체의 equals 메소드를 호출합니다. 

자바의 경우와 다른 것을 알 수 있습니다. 자바 참조타입의 “==“연산자는 scala에서 “eq” 메소드가 되겠습니다.

그래서 아래 코드와 같이 참조가 다르지만 List 내부에 equals 메소드를 호출해 내부 값을 비교하기 때문에 결과값이 true가 됩니다.

또한 오른쪽과 같이 equals로 값을 비교하기 때문에 다른 타입간 비교도 가능합니다.

 

스칼라에서는 연산자 우선순위를 연산자의 첫 글자를 보고 정합니다.

왼쪽 표, 위쪽으로 갈수록 연산자 우선순위가 높습니다. 그래서 2+2*7 의 경우 첫 글자인 *하고 + * 의 우선순위가 높기 때문에 *가 먼저 수행됩니다.

+++, ***도 같습니다. 메소드 이름이 +++, ***이고 파라미터를 받으면 중위 연산자처럼 사용 가능하기 때문에 a+++b***c 라는 표현이 가능하고

메소드의 제일 앞 글자인 +* *의 우선순위가 높기 때문에 a+++(b***c) 로 계산됩니다.

첫 글자로 우선순위를 결정하는 방법에서 예외가 있는 데 “=“로 끝나는 메소드(할당 연산자)이고 비교 연산자가 아닐 경우입니다. 그 때는 해당 연산자 우선순위는 “=“과 같습니다.

그래서 x*=y+1 의 경우 단순히 첫 글자만 보면 x*=y 연산이 먼저 이루어져야 하지만 *=는 예외 사항이기 때문에 =과 우선순위가 같습니다.

그래서 x*= (y+1) 이 됩니다.

그리고 동일한 우선 순위가 여러 개일 때는 왼쪽부터 계산하지만 연산자가 “:”로 끝나면 오른쪽부터 계산합니다.

“:” 연산자는 보통 리스트를 추가할 때하는 것으로 “:” 연산자는 뒤에 있는 객체의 메소드로 호출되기 때문에 “:”로 끝나면 오른쪽부터 계산하게 됩니다.

 

왼쪽 표를 보면 기본 타입 객체에 대해 max, min, abs 등 유용한 메소드를 호출할 수 있습니다.

그런데 이 메소드들은 기본 타입 Int, String 같은 객체에 정의되어 있지 않습니다.

이들은 각 기본 타입 클래스의 래퍼 클래스에 정의되어 있습니다. 스칼라에서는 내부적으로 max, min 같은 메소드를 호출하면 암시적 변환을 해서 래퍼 클래스에 있는 메소드를 호출하게 합니다.

이에 대해서는 나중에 더 알아볼 예정입니다.

+ Recent posts