티스토리 뷰
반응형
[Kotlin in Action - http://www.yes24.com/Product/Goods/55148593]
2.1 기본 요소: 함수와 변수
2.1.1 Hello, World!
fun main(args: Array<String>) {
println("Hello, World!")
}
- 함수를 선언할 때 fun 키워드를 사용한다
- 파라미터 이름 뒤에 그 파라미터의 타입을 쓴다
- 함수를 최상위 수준에 정의할 수 있다
- 배열도 일반적인 클래스와 마찬가지다
- 코틀린 표준 라이브러리는 여러 가지 표준 자바 라이브러리 함수를 간결하게 사용할 수 있게 감싼 래퍼(wrapper)를 제공한다
- 줄 끝에 세미콜론(;)을 붙이지 않아도 된다
2.1.2 함수
- 함수 선언은 fun 키워드로 시작한다
- fun 다음에는 함수 이름이 온다
- 함수 이름 뒤에는 괄호 안에 파라미터 목록이 온다
- 함수의 반환 타입은 파라미터 목록의닫는 괄호 뒤에 오는데, 괄호와 반환 타입 사이를 콜론(:)으로 구분해야 한다
- 코틀린 if는 문장(statement)이 아니고 결과를 만드는 식(expression)이다
- 문(statement)와 식(expression)의 구분
- 식은 값을 만들어 내며 다른 식의 하위 요소로 계산에 참여할 수 있는 반면
문은 자신을 둘러싸고 있는 가장 안쪽 블록의 최상위 요소로 존재하며 아무런 값을 만들어내지 않는다 - 코틀린에서는 루프를 제외한 대부분의 제어 구조가 식이다
- 대입문은 자바에서 식이었으나 코틀린에서는 문이 됐다
- 식은 값을 만들어 내며 다른 식의 하위 요소로 계산에 참여할 수 있는 반면
- 문(statement)와 식(expression)의 구분
- 식이 본문인 함수
- 블록이 본문인 함수 : 본문이 중괄호로 둘러싸인 함수
식이 본문인 함수 : 등호와 식으로 이뤄진 함수 - 식이 본문인 함수의 경우 굳이 사용자가 반환 타입을 적지 않아도 컴파일러가 함수 본문 식을 분석해서 식의 결과 타입을 함수 반환 타입으로 정해준다
- 타입추론(type inference)컴파일러가 타입을 분석해 프로그래머 대신 프로그램 구성 요소의 타입을 정해주는 기능
- 식이 본문인 함수의 반환 타입만 생략 가능하다
- 블록이 본문인 함수 : 본문이 중괄호로 둘러싸인 함수
2.1.3 변수
- 코틀린에서는 키워드로 변수 선언을 시작하는 대신 변수 이름 뒤에 타입을 명시하거나 생략하게 허용한다
- 타입을 지정하지 않으면 컴파일러가 초기화 식을 분석해서 초기화 식의 타입을 변수 타입으로 지정한다
- 초기화 식을 사용하지 않고 변수를 선언하려면 변수 타입을 반드시 명시해야 한다
- 변경 가능한 변수와 변경 불가능한 변수
- val(값을 뜻하는 value에서 따옴) : 변경불가능한(immutable) 참조를 저장하는 변수
- 일단 초기화하고 나면 재대입이 불가능하다
- 자바로 치면 final 변수
- 블록을 실행할 때 정확히 한 번만 초기화돼야 한다
- 참조 자체는 불변일지라도 그 참조가 가리키는 객체의 내부 값은 변경될 수 있다
- var(변수를 뜻하는 variable에서 따옴) : 변경 가능한(mutable) 참조
- 자바의 일반 변수에 해당
- 변수의 값을 변경할 수 있지만 변수의 타입은 고정돼 바뀌지 않는다
- 기본적으로는 모든 변수를 val 키워드를 사용해 불변 변수로 선언하고 나중에 꼭 필요할 때만 var로 변경해라
- 변경 불가능한 참조와 변경 불가능한 객체를 부수효과가 없는 함수와 조합해 사용하면 코드가 함수형 코드에 가까워진다
- 컴파일러는 변수 선언 시점의 초기화 식으로부터 변수의 타입을 추론하며, 변수 선언 이후 변수 재대입이 이뤄질 때는 이미 추론한 변수의 타입을 염두에 두고 대입문의 타입을 검사한다
- val(값을 뜻하는 value에서 따옴) : 변경불가능한(immutable) 참조를 저장하는 변수
2.4.1 더 쉽게 문자열 형식 지정: 문자열 템플릿
- 문자열 템플릿(string template)
- 문자열 리터럴의 필요한 곳에 변수를 넣되 변수 앞에 $를 추가하면 된당
2.2 클래스와 프로퍼티
- 값 객체(value object) : 코드가 없이 데이터만 저장하는 클래스
- 코틀린의 기본 가시성은 public
2.2.1 프로퍼티
- 클래스의 목적 : 데이터를 캡슐화(encapsulate)하고 캡슐화한 데이터를 다루는 코드를 한 주체 아래 가두는 것
- 자바에서는 필드(field, 데이터 저장)와 접근자(access method, 데이터에 접근하는 통로)를 한데 묶어 프로퍼티라고 부르는데
코틀린의 프로퍼티(property)는 자바의 필드와 접근자 메소드를 완전히 대신한다- 클래스에서 프로퍼티를 선언할 때는 val(읽기 전용), var(변경 가능)을 사용한다
- 기본적으로 코틀린에서 프로퍼티를 선언하는 방식은 프로퍼티와 관련 있는 접근자를 선언하는 것이다
- 코틀린은 값을 저장하기 위한 비공개 필드와 그 필드에 값을 저장하기 위한 세터, 필드의 값을 읽기 위한 게터로 이뤄진 간단한 디폴트 접근자 구현을 제공한다
class Person(
val name: String, // (비공개) 필드, (공개) 게터
var isMarried: Boolean, // (비공개) 필드, (공개) 게터, (공개) 세터
)
- 이름이 is로 시작하는 프로퍼티의 게터에는 get이 붙지 않고 원래 이름을 그대로 사용하며, 세터에는 is를 set으로 바꾼 이름을 사용한다
val person = Person("Bob", true) // new 키워드를 사용하지 않고 생성자를 호출한다
println(person.name) // 프로퍼티 이름을 직접 사용해도 코틀린이 자동으로 게터를 호출해준다
println(person.isMarried)
person.isMarried = false // 프로퍼티 이름을 직접 사용해도 코틀린이 자동으로 세터를 호출해준다
- 대부분의 프로퍼티에는 그 프로퍼티의 값을 저장하기 위한 필드가 있다 -> 뒷받침하는 필드(backing field)
- 커스텀 게터를 작성해서 프로퍼티 값을 그때그때 계산할 수도 있다
2.2.2 커스텀 접근자
class Rectangle(val height: Int, val width: Int) {
val isSquare: Boolean
get() { // 프로퍼티 게터 선언
return height == width
}
}
- 클라이언트가 프로퍼티에 접근할 때마다 게터가 프로퍼티 값을 매번 다시 계산
2.2.3 코틀린 소스코드 구조: 디렉터리와 패키지
- 코틀린 파일의 맨 앞에 package 문을 넣으면 그 파일 안에 있는 모든 선언이 해당 패키지에 들어간다
- 같은 패키지에 속해 있다면 다른 파일에서 정의한 선언일지라도 직접 사용할 수 있다
- 다른 패키지에 정의한 선언을 사용하려면 임포트를 통해 선언을 불러와야 한다
- 코틀린에서는 클래스 임포트와 함수 임포트에 차이가 없으며, 모든 선언을 import 키워드로 가져올 수 있다
- 최상위 함수는 그 이름을 써서 임포트할 수 있다
- 패키지 이름 뒤에 .*를 추가하면(start import) 패키지 안의 모든 선언을 임포트할 수 있다
- 패키지 안의 모든 클래스, 최상위 함수, 프로퍼티 를 모두 불러온다
- 코틀린에서는 여러 클래스를 한 파일에 넣을 수 있고 파일의 이름도 마음대로 정할 수 있다
- 코틀린에서는 디스크상의 어느 디렉터리에 소스코드 파일을 위치시키든 관계없다
- 하지만 대부분의 경우 자바와 같이 패키지별로 디렉터리를 구성하는 편이 낫다
2.3 선택 표현과 처리: enum과 when
2.3.1 enum 클래스 정의
- 코틀린에서 enum은 소프트 키워드로 class 앞에 있을 때만 특별한 의미를 지닌다
- enum 클래스 안에 프로퍼티나 메소드, 생성자를 정의할 수 있다
- enum 클래스 안에 메소드를 정의하는 경우 반드시 enum 상수 목록과 메소드 정의 사이에 세미콜론을 넣어야 한다
2.3.2 when으로 enum 클래스 다루기
fun getMnemonic(color: Color) = // 함수의 반환 값으로 when식을 직접 사용
when (color) {
Color.RED -> "Richard"
Color.ORANGE -> "Of"
Color.YELLOW -> "York"
Color.GREEN -> "Gave"
Color.BLUE -> "Battle"
Color.INDIGO -> "In"
Color.VIOLET -> "Vain"
}
- when도 값을 만들어내는 식
- 자바와 달리 각 분기의 끝에 break를 넣지 않아도 된다
- 한 분기 안에서 여러 값을 매치 패턴으로 사용할 수도 있다. 그럴 경우 값 사이를 콤마(,)로 분리한다
2.3.3 when과 임의의 객체를 함께 사용
fun mix(c1: Color, c2: Color) =
when (setOf(c1, c2)) {
setOf(RED, YELLOW) -> ORANGE
setOf(YELLOW, BLUE) -> GREEN
setOf(BLUE, VIOLET) -> INDIGO
else -> throw Exception("Dirty color") // 매치되는 분기 조건이 없으면 이 문장을 실행
}
- 코틀린 when의 분기 조건은 임의의 객체를 허용한다
- when 식의 인자로 아무 객체나 사용할 수 있다. when은 이렇게 인자로 받은 객체가 각 분기 조건에 있는 객체와 같은지 테스트한다
- 여기서 동등성(equality)을 사용한다
- when의 분기 조건 부분에 식을 넣을 수 있기 때문에 많은 경우 코드를 더 간결하고 아름답게 작성할 수 있다
2.3.4 인자 없는 when 사용
- when에 아무 인자도 없으려면 각 분기의 조건이 Boolean 결과를 계산하는 식이어야 한다
- 추가 객체를 만들지 않는다는 장점이 있지만 가독성은 더 떨어진다
2.3.5 스마트 캐스트: 타입 검사와 타입 캐스트를 조합
- 클래스가 구현하는 인터페이스를 지정하기 위해서 콜론(:) 뒤에 인터페이스 이름을 사용
- 코틀린에서는 is를 사용해 변수 타입을 검사한다
- 스마트 캐스트
- 어떤 변수가 원하는 타입인지 is로 검사하고 나면 굳이 변수를 원하는 타입으로 캐스팅하지 않아도 마치 처음부터 그 변수가 원한느 타입으로 선언된 것처럼 사용할 수 있다. 하지만 실제로는 컴파일러가 캐스팅을 수행해준다
- 스마트 캐스트는 is로 변수에 든 값의 타입을 검사한 다음에 그 값이 바뀔 수 없는 경우에만 작동한다
- 클래스의 프로퍼티에 대해 스마트 캐스트를 사용한다면 그 프로퍼티는 반드시 val이어야 하고 커스텀 접근자를 사용한 것이어도 안 된다
- 원하는 타입으로 명시적으로 타입 캐스팅하려면 as 키워드를 사용한다
2.3.6 리팩토링: if를 when으로 변경
- 코틀린에서는 if가 값을 만들어 내기 때문에 자바와 달리 3항 연산자가 따로 없다
- if 분기에 블록을 사용하는 경우 그 블록의 마지막 식이 그 분기의 결과 값이다
2.3.7 if와 when의 분기에서 블록 사용
- if나 when 모두 분기에 블록을 사용할 수 있고 그런 경우 블록의 마지막 분장이 블록 전체의 결과가 된다
- '블록의 마지막 식이 블록의 결과'라는 규칙은 블록이 값을 만들어내야 하는 경우 항상 성립한다
- 식이 본문 함수는 블록을 본문으로 가질 수 없고 블록이 본문인 함수는 내부에 return 문이 반드시 있어야 한다
2.4 대상을 이터레이션: while과 for 루프
- for는 자바의 for-each 루프에 해당하는 형태만 존재
2.4.1 while 루프
while (조건) { // 조건이 참인 동안 본문을 반복 실행한다
/*...*/
}
do { // 맨 처음에 무조건 본문을 한 번 실행한 다음,
// 조건이 참인 동안 본문을 반복 실핸한다
/*...*/
} while (조건)
2.4.2 수에 대한 이터레이션: 범위와 수열
- 범위(range) : 두 값으로 이뤄진 구간
- 보통은 그 두 값은 정수 등의 숫자 타입의 값이며 . 연산자로 시작 값과 끝 값을 연결해서 범위를 만든다
- 코틀린의 범위는 폐구간(닫힌 구간)
- step 으로 증가값을 나타낼 수 있음
- ex) 100 downTo 1 step 2 : 100부터 1까지 2씩 작아지는 역방향 수열(100, 98, ... 2)
- 수열(progression) : 어떤 범위에 속한 값을 일정한 순서로 이터레이션하는 경우
- until 함수를 사용해서 반만 닫힌 범위를 할 수 있음
- ex) x in 0 until size는 x in 0..size-1과 동일하다
2.4.3 맵에 대한 이터레이션
- .. 연산자를 숫자 타입의 값뿐 아니라 문자 타입의 값에도 적용할 수 있다
- get 과 put 을 사용하는 대신 map[key] 나 map[key]=value 를 사용해 값을 가져오고 설정할 수 있다
- 맵에 상요했던 구조 분해 구문을 맵이 아닌 컬렉션에서도 사용할 수 있다
- 구조분해 -> for((letter, binary) in binaryReps){... 요거
- 구조 분해 구문을 사용하면 원소의 현재 인덱스를 유지하면서 컬렉션을 이터레이션할 수 있다
인덱스를 저장하기 위한 변수를 별도로 선언하고 루프에서 매번 그 변수를 증가시킬 필요가 없다
val list = arrayListOf("10", "11", "1001")
for ((index, element) in list.withIndex()) { // 인덱스와 함께 컬렉션을 이터레이션한다
println("$index: $element")
}
2.4.4 in으로 컬렉션이나 범위의 원소 검사
- in 연산자를 사용해 어떤 값이 범위에 속하는지 검사할 수 있음
!in을 사용하면 어떤 값이 범위에 속하지 않는지 검사할 수 있음- when 식, 컬렉션에서 사용해도 된다
- 비교가 가능한 클래스라면(java.lang.Comparable 인터페이스를 구현한 클래스라면) 그 클래스의 인스턴스 객체를 사용해 범위를 만들 수 있다
- Comparable을 사용하는 범위의 경우 그 범위 내이 모든 객체를 항상 이터레이션하지는 못한다
- 하지만 in연산자를 사용하면 값이 범위안에 속하는지 항상 결정할 수 있다
2.5 코틀린의 예외 처리
- 예외 인스턴스를 만들 때 new를 붙일 필요가 없다
- 코틀린의 throw는 식이므로 다른 식에 포함될 수 있다
2.5.1 try, catch, finally
- 함수가 던질 수 있는 예외를 명시할 필요가 없음 -> throws 절을 안 적어도 된다
- 코틀린은 체크 예외(checked exception)과 언체크 예외(unchecked exception)을 구분하지 않는다
2.5.2 try를 식으로 사용
- 코틀린의 try는 식이므로 try의 값을 변수에 대입할 수 있다
- if와 달리 try의 본문을 반드시 중괄호 {}로 둘러써야 한다
- try의 본문도 내부에 여러 문장이 있으면 마지막 식의 값이 전체 결과 값이다
- catch 블록도 그 안의 마지막 식이 블록 전체의 값이 된다
2.6 요약
- 함수를 정의할 때 fun 키워드를 사용한다. val과 var는 각각 읽기 전용 변수와 변경 가능한 변수를 선언할 때 쓰인다
- 문자열 템플릿을 사용하면 문자열을 연결하지 않아도 되므로 코드가 간결해진다. 변수 이름 앞에 $를 붙이거나, 식을 ${식}처럼 ${ }로 둘러싸면 변수나 식의 값을 문자열 안에 넣을 수 있다
- 코틀린에서는 값 객체 클래스를 아주 간결하게 표현할 수 있디
- 디른 언어에도 있는 if는 코틀린에서 식이며, 값을 만들어낸다
- 코틀린 when은 자바의 swtich와 비슷하지만 더 강력하다
- 어떤 변수의 타입을 검사하고 나면 굳이 그 변수를 캐스팅하지 않아도 검사한 타입의 변수처럼 사용할 수 있다. 그런 경우 컴파일러가 스마트 캐스트를 할용해 자동으로 타입을 바꿔준다
- for, while, do-while 루프는 자바가 제공하는 같은 키워드의 기능과 비슷하다. 하지만 코틀린의 for는 자바의 for보다 더 편리하다. 특히 맵을 이터레이션하거나 이터레이션하면서 컬렉션의 원소와 인덱스를 함께 사용해야 하는 경우 코틀린의 for가 더 편리하다
- 1..5와 같은 식은 범위를 만들어낸다. 범위와 수열은 코틀린에서 같은 뭄법을 사용하며, for 루프에 대해 같은 추상화를 제공한다. 어떤 값이 범위 안에 들어 있거나 들어있지 않은지 검사하기 위해서 in이나 !in을 사용한다
- 코틀린 예외 처리는 자바와 비슷하다. 다만 코틀린에서는 함수가 던질 수 있는 예외를 선언하지 않아도 된다
반응형
'study > kotlin in action' 카테고리의 다른 글
부록E. 코루틴과 Async/Await (0) | 2022.04.18 |
---|---|
3. 함수 정의와 호출 (0) | 2022.01.09 |
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Kubernetes
- 자바
- 도커
- kotlin In Action
- back merge
- linuxkit
- clean code
- springboot
- kotlin
- cacheable
- gasmask
- JavaScript
- 스프링
- docker pull limit
- ddd
- 코틀린
- docker
- IntelliJ
- Spring
- gradle
- k8s
- ImagePullBackOff
- 도메인주도설계
- docker for mac
- 자바스크립트
- 스프링부트
- QuickTimePlayer
- 클린코드
- 쿠버네티스
- java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함