해당 내용은 이지스 퍼블리싱 카페에서 공부하며 올렸던 글을 다듬었습니다.
< 코틀린 언어 소개 >
- 코틀린 파일의 확장자 : .kt
- 코틀린 컴파일러(kotlinc)가 .kt 파일을 컴파일하면 자바 바이트 코드가 만들어진다.
- 코틀린의 이점 4가지
* 표현력과 간결함 => 훨씬 간결한 구문으로 프로그램 작성 가능
* 안전한 코드 => 자바의 런타임 오류인 널 포인트 예외를 고려하지 않고 개발 가능
널 허용(nullable)과 널 불허용(not null)으로 구분해서 선언 가능
* 상호 운용성 => 코트린은 자바와 100% 호환
* 구조화 동시성 => 코루틴(coroutines) 기법을 이용해 비동기 프로그래밍을 간소화
ex) 네트워크 연동, 데이터 베이스 갱신 등
- package : 이 파일을 컴파일했을 때 만들어지는 클래스 파일의 위치를 나타내며
소스 파일에서 맨 처음 한 줄로 선언
- import : package 구문 아래에 여러 줄 작성 가능
어떤 파일에 선언한 멤버(변수, 함수, 클래스)를 다른 코틀린 파일에서 참조할 때
package 구문
|
import 구문
|
같게 선언
|
X
|
다르게 선언
|
O
|
코틀린 파일을 컴파일하면 클래스는 각각의 클래스 파일로 만들어진다.
User.kt라는 파일 내 클래스를 선언했다면 User.class 파일이 만들어지고, (User.class)
최상위에 선언한 변수와 함수는 자동으로 '파일명+Kt'라는 이름의 클래스에 포함된다. (UserKt.class)
P.82 참고
< 변수와 함수 >
- 변수 : val, var 키워드로 선언
* val : value. 초깃값 할당 후 바꿀 수 없는 변수 (상수)
* var : variable. 초깃값 할당 후 바꿀 수 있는 변수 (변수)
val(혹은 var) 변수명: 타입 = 값
- 타입 지정과 타입 추론
* 변수명 뒤에 콜론(:)을 추가해서 타입 명시 가능
* 대입하는 값에 따라 타입을 유추할 수 있을 때(타입 추론)는 생략 가능
val data1: Int = 10 // 타입 지정
val data2 = 10 // 타입 추론
- 최상위에서 선언한 변수나 클래스의 멤버 변수는 선언과 동시에 초기화해야 함
- 초기화 미루기
* lateinit 키워드
=> var 키워드로 선언한 변수만 사용 가능
=> String 타입에만 사용 가능
* lazy 키워드
=> 변수 선언문 뒤 by lazy { } 형식으로 선언
=> 변수가 최초로 이용되는 순간 중괄호로 묶은 부분이 자동으로 실행됨
=> lazy문의 중괄호를 여러 줄로 작성한다면 마지막 줄의 실행 결과가 변수의 초깃값이 됨
val data4: Int by lazy {
println("in lazy...")
10
}
fun main() {
println("in main...")
println(data4 + 10)
}
------< 실행 결과 >------
in main...
in lazy...
20
- 코틀린의 모든 변수는 객체
- null은 메모리 할당이 되지 않았음을 의미
- 기초 타입 객체 : Int, Short, Long, Double, Float, Byte, Boolean
var data1: Int = 10 // 기초 타입
var data2: Int? = null // 객체 타입
- String은 큰따옴표(")나 삼중 따옴표(""")로 감싸서 표현
* 삼중 따옴표는 정렬한 그대로 출력함
- 문자열 템플릿 : String 타입의 데이터에 변숫값이나 어떤 연산식의 결괏값을 포함해야 할 때는 $ 기호를 이용
예) ${arr1[0]}
// 삼중 따옴표 사용 예시
println(
"""
array size : ${arr1.size}
array data : ${arr1[0]}, ${arr1[1]}, ${arr1.get(2)}
"""
)
- Any : 모든 타입의 데이터 할당 가능
- Unit : 반환 문이 없는 함수
* 특수한 상황을 표현하려는 목적
* Unit 타입으로 선언한 변수에는 Unit 객체만 대입 가능 => 선언할 수 있지만 의미 없음
* 주로 함수에서 반환문이 없음을 명시적으로 나타낼 때 사용
* 함수 선언 시 반환 타입을 생략하면 자동으로 Unit이 적용됨
- Nothing : null이나 예외 반환
* 주로 함수 반환 타입에 사용
* 반환하지만 의미 있는 값은 아니라는 의미
// Any 사용 예시
val data1: Any = 10
class User
val data3: Any = User()
// Unit 사용 예시
val data1: Unit = Unit // 가능하지만 의미 없음
fun someFun(): Unit { // 반환문이 없는 함수
println(10+20)
}
fun someFun() { // 위와 같은 함수 (명시하지 않아도 자동 적용)
println(10+20)
}
// Nothing 사용 에시
val data1: Nothing? = null
fun some1(): Nothing? { // null 반환
return null
}
fun some2(): Nothing { // 예외 반환
throw Exception()
}
}
- 널 허용과 널 불허용
* nullable : 널 허용. null을 대입할 수 있는 변수
=> 타입 뒤에 물음표(?)로 표시
* not null : 널 불허용. null을 대입할 수 없는 변수
var data1: Int = 10
data1 = null // 오류
var data2: Int? = 10
data2 = null // 성공
- 함수 : fun 키워드 사용
* 매개변수에는 var나 val 사용 불가
=> val 자동 적용
=> 함수 안에서 매개 변숫값 변경 불가
- 함수의 매개변수에는 기본값 선언 가능
* 호출할 때 인자를 전달하지 않아도 됨
fun main() {
fun some(data1: Int, data2: Int=10): Int {
return data1 * data2
}
println(some(10)) // 두번째 인자는 기본값 10으로 처리
println(some(10, 20)) // 두번째 인자는 20으로 처리
}
- 함수의 매개변수는 전달한 인자를 순서대로 할당
* 호출할 때 매개변수명을 지정(명명된 매개변수)하면 매개 변숫값의 순서를 바꿔도 됨
some(data2 = 20, data1 = 10)
- 컬렉션 타입 : 여러 개의 데이터를 표현하는 방법
* Array, List, Set, Map
- Array : 배열 표현
* 매개변수
=> 첫 번째 : 배열의 크기
=> 두 번째 : 초깃값
* 배열 타입은 제너릭으로 표현
=> 제너릭 : 이용하는 곳에서 타입을 지정하는 기법
val data1: Array<Int> = Array(3, { 0 }) // 기본 방식
val data1: Array<Int> = Array(3) { 0 } // 최근 버전에선 이 방식을 추천함
* 배열에 접근할 때는 대괄호([])나 set(), get() 함수를 이용할 수 있음
=> 최신 버전에선 대괄호([]) 방법으로 추천함
// Array 객체 타입 예제
val arr1: Array<Int> = Array(3, { 0 }) // 배열 선언. Array(배열의 크기, 초깃값)
arr1[0] = 10
arr1[1] = 20 // 대괄호([]) 형태
arr1.set(2, 30) // set(인덱스, 값) 형태로 설정하기
println(
"""
array size : ${arr1.size}
array data : ${arr1[0]}, ${arr1[1]}, ${arr1.get(2)} // get(인덱스) 형태로 가져오기
"""
)
- 기초 타입의 배열 : Array를 사용하지 않고 각 기초 타입의 배영을 나타내는 클래스를 이용할 수도 있음
* BooleanArray, ByteArray, CharArray, DoubleArray, FloatArray, IntArray, ShortArray 클래스 이용 가능
val data1: IntArray = IntArray(3, { 0 })
- arrayOf() 함수
* 기초 타입도 있음 => booleanArrayOf(), byteArrayOf(), charArrayOf() 등
val data1 = arrayOf<Int>(10, 20, 30) // arrayOf()로 배열 선언. 각 인덱스에 초깃값 할당
val data2 = intArrayOf(10, 20, 30) // intArrayOf() 기초 타입 함수.
- 컬렉션 타입 클래스: List, Set, Map
순서
|
중복 허용
|
|
List
|
O
|
O
|
Set
|
O
|
X
|
Map
|
X
|
X (키의 중복만)
|
- 컬렉션의 가변 클래스와 불변 클래스
* 가변 : 초깃값을 대입한 이후에도 데이터를 추가하거나 변경 가능
=> mutableListOf(), mutableSetOf(), mutableMapOf()
* 불변 : 초기에 데이터를 대입하면 변경 불가
=> listOf(), setOf(), mapOf()
- Map 객체 : 키와 값으로 구성
* 키와 값을 설정하는 2가지 방법
① Pair
② '키 to 값'
// Map 예제
var map = mapOf<String, String>(Pair("one", "one hello"), "two" to "two world")
println(
"""
map size: ${map.size}
map data: ${map.get("one")}, ${map.get("two")}
"""
)
---------- < 실행 결과 > ----------
map size: 2
map data: one hello, two world
< 조건문과 반복문 >
- if~else : 조건문. 프로그램의 흐름을 제어하는데 가장 많이 사용.
* 표현식으로 표현 가능. 단, else 생략할 수 없음!
* 표현식이 반환하는 결괏값은 각 영역의 마지막 줄에 해당함.
var data = 10
val result = if (data > 0) { // 표현식은 else문 생략 불가!!
println("data > 0")
true // 참일 때 반환값
} else {
println("data <= 0")
false // 거짓일 때 반환값
}
printf(result)
---------- < 실행 결과 > ----------
data > 0
true
----------------------------------
- when : 조건문. (switch와 비슷)
* 정수가 아닌 다른 타입의 데이터를 지정 가능.
// 1. 문자열 예제
var data1 = "hello"
when (data1) {
"hello" -> println("data is hello")
"world" -> println("data is world")
else -> {
println("data is not valid data")
}
}
---------- < 실행 결과 > ----------
data is hello
----------------------------------
// 2. 다양한 유형의 조건 예제
var data2: Any = 10
when (data2) {
is String -> println("data is String") // data가 문자열 타입이면
20, 30 -> println("data is 20 or 30") // data가 20 또는 30이면
in 1..10 -> println("data is 1..10") // data가 1~10의 값이면
else -> println("data is not valid")
}
---------- < 실행 결과 > ----------
data is 1..10
----------------------------------
* 데이터를 명시하지 않고 조건만 명시 가능.
// 3. 조건만 명시한 예제
var data3 = 10
when { // 데이터를 명시하지 않음
data3 <= 0 -> println("data is <= 0")
data3 > 100 -> println("data is > 100")
else -> println("data is valid")
}
---------- < 실행 결과 > ----------
data is valid
----------------------------------
* when문도 표현식으로 사용 가능!
if문의 표현식처럼 else문 생략 불가!
// 4. when문을 표현식으로 사용한 예제
var data4 = 101
var result = when {
data4 <= 0 -> "data is <= 0"
data4 > 100 -> "data is > 100"
else -> "data is valid"
}
println(result)
---------- < 실행 결과 > ----------
data is > 100
----------------------------------
- for : 반복문. 제어 변숫값을 증감하면서 특정 조건이 참일 때까지 구문을 반복해서 실행.
* 범위 연산자인 in을 사용
// 기본 예제
var sum: Int = 0
for (i in 1..10) { // 범위 연산자 in => 1부터 10까지
sum += i
}
println(sum)
---------- < 실행 결과 > ----------
55
----------------------------------
* 증감 조건을 숫자로 명시하지 않고 컬렉션 타입의 데이터도 표현 가능
var data = arrayOf<Int>(10, 20, 30)
for(i in data.indices) { // indices = '컬렉션 타입의 인덱스 값'을 의미
print(data[i])
if(i !== data.size - 1) {
print(", ")
}
}
---------- < 실행 결과 > ----------
10, 20, 30
----------------------------------
* 인덱스와 데이터를 함께 가져오려면 withIndex() 함수 이용
// 인덱스와 데이터를 가져오는 withIndex() 함수
var data1 = arrayOf<Int>(10,20,30)
for ((index, value) in data.withIndex()) {
print(value)
if(index !== data.size - 1) print(",")
}
---------- < 실행 결과 > ----------
10,20,30
----------------------------------
- while : 반복문. 조건이 참이면 중괄호{} 영역을 반복해서 실행.
var x = 0
var sum1 = 0
while (x < 10) { // x < 10이 참(true)이면
sum1 += ++x
}
println(sum1)
---------- < 실행 결과 > ----------
55
----------------------------------
'Programming > Kotlin' 카테고리의 다른 글
[5일차] 깡샘의 안드로이드 앱 프로그래밍 with 코틀린(Do it!) / 05 코틀린의 유용한 기법 (0) | 2021.12.21 |
---|---|
[4일차] 깡샘의 안드로이드 앱 프로그래밍 with 코틀린(Do it!) / 04 코틀린 객체지향 프로그래밍 (0) | 2021.12.17 |
[2일차] 깡샘의 안드로이드 앱 프로그래밍 with 코틀린(Do it!) / 02 안드로이드 앱의 기본 구조 (0) | 2021.12.02 |
[1일차] 깡샘의 안드로이드 앱 프로그래밍 with 코틀린(Do it!) / 01 개발 환경 준비하기 (0) | 2021.12.01 |
Kotlin 공부를 시작하다! (0) | 2021.12.01 |