코틀린의 특성
정적 타입 지정 언어 (statically typed)
프로그램 구성 요소의 타입을 컴파일 시점에 알 수 있음
프로그램 안에서 객체의 필드나 메소드를 사용할때마다 타입을 검증
↔ 동적 타입 지정 언어 (dynamically typed)
타입과 관계없이 모든 값을 변수에 넣을 수 있음
메소드나 필드 접근에 대한 검증이 실행 시점에 일어남
코틀린은 정적 타입 지정 언어!
코틀린에서는 모든 변수의 타입을 프로그래머가 직접 명시할 필요가 없음
타입 추론(type inference)
컴파일러가 문맥으로부터 변수 타입을 자동으로 유추할 수 있음
var x= 1
//변수를 정의하면서 정수 값으로 초기화 한다.
//코틀린은 이 변수 타입이 int 임을 자동으로 알아낸다.
코틀린은 널이 될 수 있는 타입을 지원한다. (nullable type)
코틀린의 타입 시스템은 null이 될 수 없는 값을 추적함
실행 시점에 NullPointerException이 발생할 수 있는 연산을 사용하는 코드를 금지
어떤 타입이 null이 될 수 있는 지 여부를 표시하기 위해서는 ? 를 추가하면 된다.
val s:String? = null ←널이 될 수 있다
val s2:String = “” ←널이 될 수 없다
이런식으로 앱에서 NullPointerException으로 인해 갑자기 중단되는 경우를 줄여준다.
코틀린은 객체지향과 함수형 프로그래밍 스타일을 모두 지원한다.
함수형 프로그래밍의 핵심 개념
- 일급 시민인 함수 함수를 일반 값처럼 다룰 수 있음. 함수를 변수에 저장할 수 있고,함수를 인자로 다른 함수에 전달할 수 있음. 함수에서 새로운 함수를 만들어 반환할 수 있음.
- 불변성 만들어나지고 나면 내부 상태가 절대로 바뀌지 않는 불변 객체를 사용해 프로그램을 작성
- 부수 효과 없음 입력이 같으면 항상 같은 출력. 다른 객체의 상태를 변경하지 않고,함수 외부나 다른 바깥 환경과 상호작용하지 않는 순수 함수를 사용한다.
함수형 프로그래밍의 장점
- 간결성 명령형 코드에 비해 간결. 추상화를 통해 코드 중복을 막을 수 있음
- 다중스레드 안전 다중 스레드 프로그램에서는 적절한 동기화 없이 같은 데이터를 여러 스레드가 변경하는 경우 문제가 생김. 불변 데이터 구조를 사용하고 순수 함수를 데이터 구조에 적용하면 다중 스레드 환경에서 같은 데이터를 여러 스레드가 변경 불가능하므로 동기화 적용하지 않아도 됨.
- 테스트가 용이부수 효과가 있는 함수를 함수를 실행할때 필요한 전체 환경을 구성하는 준비 코드가 필요하지만.순수 함수는 그런 준비 코드 없이 독립적으로 테스트할 수 있음
코틀린에서의 함수형 프로그래밍 지원
- 함수 타입 지원 →어떤 함수가 다른 함수를 파라미터로 받거나 함수가 새로운 함수를 반환할 수 있다.
- 람다식 지원 → 번거로운 준비 코드를 작성하지 않아도 코드 블록을 쉽게 정의하고 여기저기 전달할 수 있다.
- 데이터 클래스는 불변적인 값 객체value objec'를 간편하게 만들 수 있는 구문을 제공한다 .
- 코틀린 표준 라이브러리는 객체와 컬렉션을 함수형 스타일로 다룰 수 있는 API를 제공한다.
프로그램 없이 코틀린 코드 작성하는 법
프로그램을 설치할 필요 없이 코틀린 코드를 작성하고 컴파일한 다음 실행할 수 있다! 코틀린의 특성을 보여주는 여러 코드 예제와 책의 모든 예제가 들어있다!
Kotlin Playground: Edit, Run, Share Kotlin Code Online
2.1 함수와 변수
함수
fun max(a:Int,b:Int):Int {
// fun + 함수 이름 + 파라미터 목록 + 함수의 반환 타입
return if(a>b) a else b
}
문(statement) 식(expression)
코틀린에서의 if 는 문이 아닌 식이다!
식 : 값을 만들어내며 다른 식의 하위 요소로 계산에 참여가능
문 : 자신을 둘러싸고 있는 가장 안쪽 블록의 최상위 요소로 존재하며 아무런 값을 만들어내지 않음
코틀린에서는 루프를 제외한 대부분의 제어 구조가 식이다
식이 본문인 함수 : 본문이 중괄호로 둘러싸인 함수
중괄호를 없애고 return을 제거함 등호(=)를 식 앞에 붙임
fun max(a:Int,b:Int):Int = if(a>b) a else b
fun max(a:Int,b:Int)= if(a>b) a else b
반환 타입을 생략해 함수를 더 간략하게 만들 수 있다
반환 타입을 생략할 수 있는 이유 : 코틀린은 정적 타입 지정 언어이므로 컴파일 시점에 모든 식의 타입을 지정한다. 굳이 사용자가 반환 타입을 적지 않아도 컴파일러가 본문 식을 분석해 식의 결과 타입을 함수 반환 타입으로 결정한다.
변수
val answer = 42
val answer:Int = 42
타입을 지정하지 않으면 컴파일러가 초기화 식을 분석해 타입을 지정
초기화식이 42로 INT타입이므로 변수도 INT 타입이 됨
만약 val answer = 42.1 이라면 변수타입은 Double!
초기화식을 사용하지 않고 변수를 선언하려면 타입을 반드시 명시해야 한다!
val answer : Int
answer = 42
↔ val answer 만 있어서는 안된다! 초기화식이 없다면 변수에 저장될 값에 대해 아무런 정보가 없으므로 컴파일러의 타입 추론이 불가
변경가능한 변수 val(value) 초기화한 후 다시 대입 불가능
변경불가능한 변수 var(variable) 변수의 값이 바뀔 수 있음
→기본적으로 모든 변수는 val 키워드를 사용해 불변 변수로 선언하고 나중에 필요한 경우에만 var로 변경하는 것을 추천!
문자열 템플릿
fun main(args:Array<String>) {
val name = if(args.size>0) args[0] else “Kotlin”
printLn(”Hello,$name!”)
}
문자열 리터럴안에서 변수를 사용한다. 문자열 리터럴의 필요한 곳에 변수를 넣되 변수 앞에 $를 추가해야 한다.
(”Hello,”+name+”!”)
과 동일한 기능이지만 훨씬 간결하고 효율적이다.
컴파일러가 각 식을 정적으로 검사하므로 존재하지 않는 변수를 문자열 템플릿 안에서 사용하면 컴파일 오류가 발생한다.
한글을 문자열 템플릿에서 사용할 경우 주의점
변수명 바로 뒤에 한글을 붙이면 영문자와 한글을 한꺼번에 식별자로 인식해 unresolced reference 오류를 발생시킨다.
“$name님 반가워요”
“${name}님 반가워요” // 처럼 변수이름을 중괄호로 감싸면 된다!
2.2 클래스와 프로퍼티
클래스의 목적 : 데이터를 캡슐화하고 캡슐화한 데이터를 다루는 코드를 한 주체 아래 가두는 것
프로퍼티 : 필드와 접근자
프로퍼티는 val(읽기전용 getter) var(getter/setter)을 사용한다.
class Person {
val name:String,
var isMarried:Boolean
)
val person = Person(”Bob”,true)
println(person.name) //Bob출력
println(person.isMarried) //true출력
프로퍼티 이름을 직접 사용해도 코틀린이 자동으로 게터를 호출한다.
2.3 enum과 when
enum class Color {
RED,ORANGE,YELLOW
}
enum은 class앞에 있을때 특별한 의미를 갖고 다른곳에서는 이름에 사용할 수 있다. enum 클래스 안에서도 프로퍼티나 메소드를 정의할 수 있다.
enum class Color (
val r:Int,val g:Int,val b:Int
) {
RED(255,0,0) , ORANGE(255,165,0) , YELLOW(255,255,0);
fun rgb() = (r*256+g)*256 + b
}
일반적인 클래스와 마찬가지로 생성자와 프로퍼티를 선언한다. 세미콜론 필수! enum 클래스 안에 메소드를 정의하는 경우 반드시 enum 상수 목록과 메소드 정의 사이에 세미콜론을 넣어야 한다.
fun getMnemonic(color:Color) =
when (color) {
[Color.RED](<http://Color.RED>) → “Richard”
[Color.ORANGE](<http://Color.ORANGE>) → “Of”
Color.YELLOW → “York”
}
fun getWramth(color:Color) = when(color) {
Color.RED,Color.ORANGE,Color.YELLOW→”warm”
}
when 분기 조건에 여러 다른 객체 사용하기
fun mix(c1:Color,c2:Color) = {
when(setOf(c1,c2)) { // 객체 집합을 만듦
setOf(RED,YELLOW) → ORANGE //객체 집합을 비교함(원소의 순서는 상관없다)
else → throw Exception(”Dirty color”)
}
인자가 없는 when
fun mix(c1:Color,c2:Color) =
when{
(c1==RED && c2== YELLOW) || (c1==YELLOW&& c2== RED ) → ORANGE
else→ throw Exception(”Dirty color”)
}
불필요한 객체 생성을 막을 수 있다. 코드의 가독성은 떨어지나 성능이 훨씬 향상된다.
if를 when으로 변경
//if
fun eval(e:Expr):Int =
if (e is Num) {
e.value
}else if (e is Sum) {
eval(e.right)+eval(e.left)
} else { throw IlleagalArgumentException(”Unknown expression”)
}
!
//when
fun eval(e:Expr):Int =
when(e) {
is Num → e.value
is Sum → eval(e.right)+eval(e.left)
else→ throw IlleagalArgumentException(”Unknown expression”)
}
if와 when의 분기에서 블록 사용
fun evalWithLoggin(e:Expr):Int =
when(e) {
is Num→ {
prinln(”num: ${e.value}”)
e.value //이 식이 블록의 마지막 식이므로 e의 타입이 Num이면 e.value가 반환된다.
}
2.4 while과 for 루프
while(조건) { }
//조건이 참인 동안 본문을 반복 실행
do{ } while(조건)
//무조건 본문을 실행한 다음,조건이 참인동안 본문을 반복실행
! 이터레이션 - 어떠한 데이터 컬렉션(자료구조)을 순회하거나 반복하는 것을 의미
for(i in 1..100) // 1-10
for(i in100 downTo 1) // 100부터 1까지 1씩 감소
for(i in100 downTo 1 step 2) // 100부터 1까지 2씩 감소
for( i in1 until 101)== for(i in 1..100) //1-100
fun isLetter(c:Char) = c in ‘a’..’z’ || c in ‘A’..’Z’
//c가 letter가 맞는지 검사한다. ‘a’≤c && c≤’z’
“kotlin” in “java”..”scale”
// “java”≤”kotlin” && “kotlin”≤”scale” → true
“kotlin” in setOf (”java”,”scala”))
//→false
범위는 문자에만 국한되지 않고 비교가 가능한 클래스라면 인스턴스 객체를 사용해 범위를 만들 수 있다.
2.5 예외처리
코틀린도 다른 언어와 예외 처리와 비슷하다. 함수에서 오류가 발생하면 예외를 던질 수 있고,함수를 호출하는 쪽에서는 예외를 잡아 처리할 수 있다.
하지만 thorws절이 코드에 없다!
→ 코틀린에서는 함수가 던지는 예외를 지정하지 않고 발생한 예외를 잡아내도 되고 잡아내지 않아도 된다.
try,catch,finally 절을 함께 사용
try readNumber(reader:BufferedReader) : Int? {
try{
val line=reader.readLine()
return Integer.parseInt(line)
}
catch(e: NumberFormatException) {
return null
}
finally {
reader.close()
}
}
try는 식이다. → try의 값을 변수에 대입할 수 있다.
try의 본문은 반드시 중괄호로 둘러싸야 한다.
본문 내부에 여러 문장이 있으면 마지막 식의 값이 전체 결과값이다.
'프로그래밍 > kotlin in action' 카테고리의 다른 글
| 5장 (1) | 2024.05.08 |
|---|---|
| 3,4장 (2) | 2024.05.05 |