책 소개
요약
1부에서는 코틀린 프로그램에 필요한 필수적인 기본 요소를 설명하며, 이를 통해 너무 복잡한 개념을 이해하기 위해 고생하지 않고 기본적인 코틀린 언어를 배울 수 있다. 2부에서는 코틀린이 제공하는 다양한 문법 설탕이나 고급 기능을 설명하면서 각 기능이 어떤 역할을 하는지 보여준다. 그 과정에서 객체지향, 함수형 프로그래밍, 제네릭스, 컬렉션을 더 잘 이해하고, 코드 작성시 코틀린의 다양한 기능을 적재적소에 활용할 수 있게 해준다. 또한 코틀린 언어의 여러 요소를 언어 명세 수준으로 설명하고 있어 책을 다 읽은 후에도 참고서로 활용할 수 있을 것이다.
이 책에서 다루는 내용
◆ 코틀린 언어를 꼭 필요한 기초적인 내용과 기초 위에 쌓아 올려야 하는 지식으로 나눠 설명
◆ 함수 오버로드 처리규칙 등 코틀린 언어의 미묘한 세부 사항을 언어 명세를 참조해 자세히 설명
◆ 형식화 문자열 등 실무에서 필요한 내용을 설명
◆ 자세한 컬렉션 라이브러리 함수 설명과 예제
◆ 2023년 코틀린 최신 버전(1.8) 대응
이 책의 대상 독자
◆ 코틀린을 자세히 알고 싶은 프로그래머
◆ 코틀린을 배웠지만 기초를 더 다지고 싶은 코틀린 프로그래머
◆ 코틀린 언어 자체가 궁금할 때 찾아볼 수 있는 참고서가 필요한 개발자
이 책의 구성
1장, ‘코틀린 시작하기’에서는 우선 코틀린 언어의 개요를 소개하고 개발 환경을 설정하는 방법을 설명한다. 이어지는 1부, ‘코틀린 퀵스타트’에서는 코틀린 언어 요소 중 프로그램을 작성할 때 꼭 필요한 필수 개념을 다룬다. 1부를 잘 읽고 언어 기본 요소를 이해해야만 코틀린 코드를 작성할 수 있고 2부 내용을 학습하기 위한 준비를 마칠 수 있다. 1부의 각 장은 다음과 같다.
2장, ‘프로그램을 이루는 기본 단위: 변수와 식, 문’에서는 코틀린 프로그램의 기본 요소를 이루는 식, 값, 타입, 변수와 기본 제어 구조인 if, when, for, while, do ... while, break, continue를 다룬다.
3장, ‘함수’에서는 함수, 지역 변수 및 지역 함수, 영역 규칙, 익명 함수, 람다, 클로저를 다루고, 다양한 파라미터 지정 방법을 설명한다.
4장, ‘클래스와 객체’에서는 객체지향의 기초를 다룬다. 클래스, 상속, 추상 클래스, 인터페이스, 프로퍼티를 설명한다.
5장, ‘예외 처리’에서는 예외 처리를 다룬다. 프로그램에서 실패를 처리하는 방법을 설명하고, 코틀린의 예외 처리 방법인 try, catch, finally를 설명한다. 또한 use() 멤버 함수를 사용해 자동 해제가 가능한 타입을 활용하는 방법도 다룬다.
6장, ‘제네릭스’에서는 타입을 파라미터로 받아 새로운 타입(클래스/인터페이스)이나 함수를 만들어내는 방법인 제네릭스를 살펴본다. 제네릭스의 개념, 코틀린에서 타입 파라미터가 포함된 클래스, 인터페이스, 함수를 선언하는 방법, 타입 바운드, 선언 지점 변성, 사용 지점 변성을 설명한다.
7장, ‘널 가능성’에서는 널 가능성을 코틀린에서 처리하는 방법을 다룬다. 널 가능성이 왜 필요한지 살펴보고, 널이 될 수 있는 타입, 스마트 캐스트, is 및 as 연산, 엘비스 연산자(?:), 안전한 호출 연산자(?.), 널 아님 단언 연산자(!!)를 설명한다.
8장, ‘패키지와 임포트’에서는 패키지를 선언하는 방법과 패키지 멤버를 임포트해 사용하는 방법, 임포트 시 새로운 이름을 지정해 이름 충돌을 막는 방법을 소개한다. 코틀린이 기본적으로 임포트해줘서 별도로 임포트하지 않아도 되는 패키지들도 설명한다.
9장, ‘코틀린 컬렉션 기초’에서는 코틀린으로 개발을 진행할 때 가장 자주 접하게 될 기초 라이브러리인 코틀린 컬렉션을 설명한다.
10장, ‘변수 선언과 기본 타입 자세히 살펴보기’에서는 기본 타입을 자세히 살펴보고, 문자열 이스케이프, 유니코드, 변수 이름 충돌을 설명한다. 그 후 lateinit var와 constval, 연산자 우선순위와 함께 모든 코틀린 연산자를 상세히 다룬다. 마지막으로는 로우(raw) 문자열과 문자열 조작 함수를 설명한다.
11장, ‘제어 구조 자세히 살펴보기’에서는 제어 구조를 더 자세히 다루고, 범위와 순열을 설명한 후 break와 continue에서 레이블을 사용하는 방법을 살펴본다.
12장, ‘함수 자세히 살펴보기’에서는 함수와 관련된 더 자세한 내용을 살펴본다. 코틀린 연산자가 어떤 연산자 함수와 연결되는지 자세히 설명하고, 확장 함수와 프로퍼티를 살펴본다. 이어서 함수 오버로드 해소 규칙을 설명하고(다소 어려운 내용이다), 파라미터에서 코틀린 영역 규칙이 적용되는 방식과 재귀 함수 및 꼬리 재귀 함수를 정의하는 방법을 다룬다. 마지막으로는 인라인 함수를 설명한다.
13장, ‘객체지향 자세히 살펴보기’에서는 객체지향과 관련해 코틀린이 제공하는 여러 가지 기능을 살펴본다. object를 사용해 싱글턴 객체를 선언하는 방법, 동반 객체, 데이터 클래스, 이넘 클래스, 값 클래스(또는 인라인 클래스), 봉인된 클래스, 부생성자, 가시성 지정자, 인터페이스 구현 위임과 프로퍼티 위임, 타입 별명을 설명한다.
14장, ‘제네릭스 2’에서는 스타 프로젝션, 타입 소거, reified 타입 파라미터를 설명하고, 영역 함수를 다룬다.
15장, ‘컬렉션 2’에서는 9장에서 배운 여러 컬렉션이 공통으로 제공하는 다양한 함수를 유형별로 설명한다. 9장에서 다룬 함수들 외에 zip(), partition(), take(), drop(), windowed(), chunked(), associate(), groupBy() 등을 설명하고 groupBy()와 관련 있는 Grouping 클래스를 살펴본 다음, fold(), groupBy() 등을 한꺼번에 처리할 수 있는 더 일반적인 함수인 aggregate()와 그 외 여러 가지 함수를 설명한다. 마지막으로는 컬렉션을 지연 처리할 수 있는 시퀀스를 살펴본다.
각 장에서 개념을 설명하고 난 후에는 직전에 배운 내용을 간단하게 스스로 검토해보도록 익힘문제를 제시하며, 각 장의 끝에는 해당 장의 내용을 정리하는 데 도움이 되는 연습문제가 있다. 이 문제들을 풀면서 배운 내용을 정리하고 내재화하길 바란다.
목차
목차
- 1장. 코틀린 시작하기
- 1.1 간략한 역사
- 1.2 코틀린 언어의 특징
- 1.3 코틀린 개발 환경과 설치 및 사용 방법
- 1.3.1 웹 도구
- 1.3.2 IDE: 인텔리J 아이디어
- 1.3.3 명령줄 도구: kotlinc와 kotlin
- 제1부 코틀린 퀵스타트
- 2장. 프로그램을 이루는 기본 단위: 변수와 식, 문
- 2.1 가장 간단한 코틀린 프로그램
- 2.2 주석
- 2.3 값과 이름, 리터럴과 변수
- 2.4 타입과 타입 지정, 타입 추론, 타입 변환
- 2.5 if, when
- 2.6 범위와 for
- 2.7 while과 do while
- 2.8 break와 continue
- 2.9 식과 연산자
- 2.10 배열
- 2.10.1 배열 선언하기
- 2.10.2 배열을 생성하는 다른 방법
- 2.10.3 원시 타입 배열과 참조 타입 배열
- 2.10.4 배열 기본 연산
- 2.11 연습문제
- 3장. 함수
- 3.1 함수
- 3.1.1 Unit 타입
- 3.2 지역 변수와 지역 함수, 정적 영역 규칙
- 3.2.1 정적 영역 규칙
- 3.3 익명 함수와 람다
- 3.3.1 익명 함수나 람다와 관련된 편의 구문
- 3.4 클로저와 값 포획
- 3.5 다양한 파라미터 정의 방법
- 3.5.1 디폴트 파라미터
- 3.5.2 이름 붙은 인자
- 3.5.3 가변 길이 인자와 스프레드 연산자
- 3.6 연습문제
- 3.1 함수
- 4장. 클래스와 객체
- 4.1 클래스
- 4.1.1 생성자에서 클래스 프로퍼티 정의하기
- 4.1.2 객체와 참조
- 4.1.3 객체의 동일성과 동등성
- 4.1.4 초기화 블록
- 4.2 상속
- 4.2.1 멤버의 상속 관계 제어: override, open, final
- 4.2.2 상속의 활용: 오버라이드를 통한 세분화와 동적 디스패치
- 4.2.3 Any와 equals(), hashCode(), toString()
- 4.2.4 is와 as, 스마트 캐스트
- 4.3 추상 클래스
- 4.4 인터페이스
- 4.4.1 인스턴스 정의와 상속하기
- 4.4.2 인터페이스 오버라이드 규칙
- 4.5 프로퍼티 정의하기: 게터, 세터, 뒷받침하는 필드
- 4.5.1 뒷받침하는 필드
- 4.5.2 뒷받침하는 필드가 없는 경우
- 4.5.3 지연 초기화 프로퍼티
- 4.5.4 프로퍼티 게터와 인자가 없는 함수 중 어느 것을 사용해야 할까?
- 4.6 연습문제
- 4.1 클래스
- 5장. 예외 처리
- 5.1 예외 던지기
- 5.1.1 예외 타입 선언하기
- 5.1.2 다양한 예외 타입
- 5.2 예외 받기: catch
- 5.2.1 예외 다시 던지기와 예외 변환해 던지기
- 5.2.2 try/catch 식
- 5.2.3 Nothing 타입
- 5.3 정리 작업: finally
- 5.3.1 자원 자동 해제를 처리하는 더 나은 방법
- 5.4 연습문제
- 5.1 예외 던지기
- 6장. 제네릭스
- 6.1 제네릭스의 필요성
- 6.2 코틀린 제네릭스 문법
- 6.3 타입 바운드
- 6.3.1 재귀적 타입 바운드
- 6.3.2 다중 바운드: where
- 6.4 선언 지점 변성: in, out
- 6.4.1 공변성
- 6.4.2 반공변성
- 6.4.3 무공변
- 6.4.4 반공변성과 공변성은 어디서 오는가?
- 6.4.5 둘 이상의 타입 파라미터가 있는 제네릭 타입의 변성 판정
- 6.4.6 선언 지점 변성과 사용 지점 변성, 타입 프로젝션
- 6.5 연습문제
- 7장. 널 가능성
- 7.1 널 도입과 널 가능성의 필요성
- 7.1.1 제네릭 타입 파라미터에서의 널 가능성
- 7.2 널이 될 수 있는 타입과 그렇지 않은 타입
- 7.3 널 여부 검사와 스마트 캐스트
- 7.3.1 널 가능성에 대한 스마트 캐스트와 Nothing 타입
- 7.3.2 널이 될 수 있는 타입의 값과 is, as 연산
- 7.4 엘비스 연산자와 안전한 호출 연산자
- 7.5 널 아님 단언 연산자
- 7.6 연습문제
- 7.1 널 도입과 널 가능성의 필요성
- 8장. 패키지와 임포트
- 8.1 패키지와 임포트
- 8.1.1 패키지 선언
- 8.1.2 전체 이름과 짧은 이름, 임포트
- 8.2 임포트 이름 충돌과 임포트 별명
- 8.3 디폴트 임포트
- 8.4 연습문제
- 8.1 패키지와 임포트
- 9장. 코틀린 컬렉션 기초
- 9.1 컬렉션 소개
- 9.1.1 컬렉션이 제공하는 연산의 분류
- 9.2 Iterable<>과 Collection<>
- 9.2.1 Iterable<>
- 9.2.2 Collection<>
- 9.2.3 MutableIterable<>과 MutableCollection<>
- 9.2.4 forEach(), forEachIndexed()
- 9.3 컬렉션 종류에 따른 생성, 원소 접근, 삽입, 삭제 방법
- 9.3.1 리스트
- 9.3.2 집합
- 9.3.3 맵
- 9.4 컬렉션 검색과 걸러내기 연산
- 9.4.1 filter(), filterNot()
- 9.4.2 filterIndexed()
- 9.4.3 filterNotNull()
- 9.4.4 indexOf(), lastIndexOf(), indexOfFirst(), indexOfLast()
- 9.5 컬렉션 변환 연산
- 9.5.1 map(), mapNotNull()
- 9.5.2 flatten()
- 9.5.3 flatMap()
- 9.5.4 mapIndexed()와 flatMapIndexed()
- 9.6 컬렉션 종합 연산
- 9.6.1 합계 연산: sum(), sumOf()
- 9.6.2 축약 연산: reduce(), reduceIndexed(), reduceIndexedNull()
- 9.6.3 오른쪽 축약 연산: reduceRight()와 reduceRightIndexed()
- 9.6.4 접기 연산: fold(), foldIndexed(), foldRight(), foldRightIndexed()
- 9.6.5 문자열 변환 연산
- 9.7 컬렉션 전체 변환 연산
- 9.7.1 리스트 변환: toList(), toMutableList()
- 9.7.2 배열 변환: toTypedArray()
- 9.7.3 집합 변환: toSet()
- 9.7.4 맵 변환: toMap(), toMutableMap()
- 9.8 기타 연산
- 9.8.1 정렬
- 9.9 연습문제
- 9.1 컬렉션 소개
- 제2부
- 10장. 변수 선언과 기본 타입 자세히 살펴보기
- 10.1 기본 데이터 타입
- 10.1.1 정수형 기본 타입
- 10.1.2 실수형 기본 타입
- 10.1.3 Boolean 타입
- 10.1.4 Char 타입
- 10.2 변수 이름
- 10.2.1 이름 규칙과 이름 충돌
- 10.2.2 lateinit 변수
- 10.2.3 const val
- 10.3 연산자와 연산자 우선순위
- 10.3.1 산술 연산자
- 10.3.2 수 타입 간의 타입 변환
- 10.3.3 복합 대입 연산
- 10.3.4 증가/감소 연산
- 10.3.5 비교 연산과 불린 연산
- 10.3.6 비트 연산과 시프트 연산
- 10.3.7 비트 연산과 부호 없는 타입
- 10.3.8 수학 연산
- 10.3.9 연산자 우선순위
- 10.4 (JVM) 문자열
- 10.4.1 로우 문자열
- 10.4.2 문자열 템플릿
- 10.4.3 문자열 조작
- 10.5 연습문제
- 10.1 기본 데이터 타입
- 11장. 제어 구조 자세히 살펴보기
- 11.1 if 식과 Nothing 타입
- 11.2 for 루프와 이터레이터의 관계: 관습에 기반한 언어 기능 제공
- 11.3 범위와 순열
- 11.3.1 범위
- 11.3.2 순열
- 11.4 break, continue와 레이블
- 11.5 연습문제
- 12장. 함수 자세히 살펴보기
- 12.1 operator 키워드와 연산자 오버로드
- 12.1.1 단항 연산자 오버로드
- 12.1.2 단항 증가/감소 연산자 오버로드
- 12.1.3 이항 산술 연산자 오버로드
- 12.1.4 이항 멤버십 연산자 오버로드
- 12.1.5 인덱스 연산자 오버로드
- 12.1.6 동등성 연산자 오버로드
- 12.1.7 비교 연산자 오버로드
- 12.1.8 복합 연산자 오버로드
- 12.1.9 호출 연산자 오버로드
- 12.1.10 멤버 함수를 중위 형식으로 쓸 수 있는 경우
- 12.1.11 구조 분해와 componentN() 연산자 함수
- 12.2 확장 함수와 확장 프로퍼티
- 12.2.1 확장 함수는 정적으로 디스패치됨
- 12.2.2 널이 될 수 있는 타입에 대한 확장 함수
- 12.2.3 확장 프로퍼티
- 12.2.4 클래스 멤버로 확장 정의
- 12.2.5 함수와 프로퍼티에 대한 참조
- 12.2.6 함수 참조의 타입
- 12.2.7 수신 객체 지정 람다와 수신 객체 지정 익명 함수
- 12.2.8 이름은 같고 파라미터만 다른 확장
- 12.3 함수 오버로드 해결
- 12.3.1 어떤 요소를 호출할 수 있을까?
- 12.3.2 오버로드 후보 집합
- 12.3.3 가장 구체적인 함수를 정하기
- 12.4 영역 규칙 다시 보기: 디폴트 파라미터, 재귀
- 12.4.1 디폴트 파라미터에서 다른 파라미터 이름 사용하기
- 12.4.2 재귀 호출과 꼬리 재귀
- 12.5 인라인 함수
- 12.5.1 고차 함수 파라미터로 전달된 람다의 인라이닝
- 12.5.2 지역 return과 비지역 return
- 12.5.3 inline에서 인라인된 람다의 전달
- 12.5.4 noline과 crossinline
- 12.5.5 인라인 프로퍼티와 인라인 확장
- 12.5.6 reified
- 12.5.7 공개된 인라인 함수의 제약 사항
- 12.6 연습문제
- 12.1 operator 키워드와 연산자 오버로드
- 13장. 객체지향 자세히 살펴보기
- 13.1 내포 클래스와 내부 클래스
- 13.1.1 내포 클래스
- 13.1.2 내부 클래스
- 13.1.3 클래스 안에 내포시킬 수 있는 대상
- 13.1.4 인터페이스 안에 내포시킬 수 있는 대상
- 13.2 object로 싱글턴 객체 선언하기
- 13.2.1 익명 객체
- 13.2.2 객체가 다른 클래스나 인터페이스 상속하기
- 13.2.3 fun interface 선언과 람다를 사용한 익명 객체 선언
- 13.2.4 동반 객체
- 13.3 데이터 클래스
- 13.3.1 데이터 타입 정의 제약 사항
- 13.3.2 copy()를 통한 객체 복사
- 13.3.3 데이터 클래스 본문에 정의된 프로퍼티
- 13.3.4 데이터 클래스의 상속
- 13.3.5 조언: 데이터 클래스는 불변 객체로만 사용하라
- 13.4 이넘 클래스로 여러 상수값 정의하기
- 13.4.1 이넘 클래스에 정의된 멤버 함수나 프로퍼티
- 13.4.2 이넘 상수: 싱글턴 객체
- 13.5 값 클래스를 통해 타입 안전성과 성능 동시에 얻기
- 13.6 봉인된 클래스나 봉인된 인터페이스를 통해 클래스 계층 제한하기
- 13.7 부생성자
- 13.7.1 주생성자가 없는 경우 부생성자
- 13.8 가시성 변경자
- 13.8.1 클래스나 객체에 선언된 이름의 가시성
- 13.8.2 패키지 최상위에 선언되는 이름의 가시성
- 13.9 위임을 통해 구현을 다른 객체에 미루기
- 13.9.1 인터페이스 구현 위임
- 13.9.2 프로퍼티 위임
- 13.9.3 코틀린이 기본 제공하는 위임
- 13.9.4 getValue()와 setValue() 규칙
- 13.9.5 위임 프로퍼티 컴파일 방법
- 13.9.6 operator fun provideDelegate()
- 13.10 타입 별명
- 13.11 연습문제
- 13.1 내포 클래스와 내부 클래스
- 14장. 제네릭스 2
- 14.1 스타 프로젝션
- 14.2 타입 소거(JVM)와 reified
- 14.2.1 타입 소거
- 14.2.2 reified: 실체화한 타입
- 14.3 영역 함수
- 14.3.1 let
- 14.3.2 run 일반 함수와 run 확장 함수
- 14.3.3 with()
- 14.3.4 also()
- 14.3.5 apply()
- 14.3.6 takeIf()와 takeUnless()
- 14.3.7 코틀린 공식 문서의 영역 함수 공식 가이드
- 14.4 연습문제
- 15장. 컬렉션 2
- 15.1 두 컬렉션을 쌍으로 연결하기, 연결을 풀어 두 컬렉션 만들기: zip(), unzip(), zipWithNext()
- 15.2 컬렉션을 조건에 따라 둘로 나누기: partition()
- 15.3 fold()나 reduce()의 진행 단계를 리스트로 돌려받기: runningFold(), runningFoldIndexed(), runningReduce(), runningReduceIndexed()
- 15.3.1 runningFold(), runningFoldIndexed()의 별명: scan()과 scanIndexed()
- 15.4 원소 선택과 제외: take(), drop(), takeLast(), dropLast(), takeWhile(), dropWhile(), takeLastWhile(), dropLastWhile()
- 15.4.1 개수로 선택하거나 제외하기: take(), drop(), takeLast(), dropLast()
- 15.4.2 앞에서부터 조건에 맞는 원소를 찾거나 제거하기: takeWhile(), dropWhile(), takeLastWhile(), dropLastWhile()
- 15.5 슬라이딩 윈도우와 덩어리로 나누기: windowed(), chunked()
- 15.6 값 연관시키기: associate(), associateBy(), associateByTo(), associateTo(), associateWith(), associateWithTo()
- 15.6.1 associate()와 associateTo()
- 15.6.2 associateBy()와 associateByTo()
- 15.6.3 associateWith()와 associateWithTo()
- 15.7 키에 따라 그룹으로 나누기: groupBy(), groupByTo()
- 15.8 그룹을 처리하기 위한 Grouping 객체 얻기: groupingBy()
- 15.8.1 키 셀렉터로 그루핑 만들기: groupingBy()
- 15.8.2 그룹별 멤버 개수 세기: eachCount()
- 15.8.3 그룹별로 reduce()한 결과를 키와 연관시키기: reduce()
- 15.8.4 그룹별로 fold()한 결과를 키에 연관시키기: aggregate()
- 15.8.5 그룹별로 누적 연산을 적용한 결과를 키에 연관시키기: aggregate()
- 15.9 조건을 만족하는 원소 검사: none(), any(), all()
- 15.10 컬렉션에 대한 집합 연산: intersect(), union(), minus()
- 15.10.1 컬렉션에 원소를 덧붙이거나 컬렉션에서 원소를 제거하는 연산: plusElement(), minusElement()
- 15.11 뒤섞기 연산: shuffled()
- 15.12 배열 연산
- 15.12.1 배열 비교: contentEquals(), contentDeepEauals()
- 15.12.2 배열의 내용 복사: copyOf(), copyOfRange(), copyInto()
- 15.12.3 배열에 값 채워 넣기: fill()
- 15.12.4 뒤섞기 연산: shuffle()
- 15.13 시퀀스
- 15.13.1 시퀀스 만들기: asSequence(), generateSequence(), sequence()
- 15.14 연습문제
- 마무리: 다음에 공부할 내용과 전체 돌아보기