이 포스팅은 고돈호 님의 이것이 안드로이드다 with 코틀린(한빛미디어)을 기반으로 작성되었습니다.
코틀린은 지연 초기화를 사용한다. 이를 통해 앞서서 포스팅한 Nullable의 남용을 방지한다.
일반적으로 Nullable로 선언한 방법은 다음과 같다.
1.1 lateinit
classPhone{
var name: String? = nullinit {
name = "iphone"
}
funprocess() {
name?.plus("13 pro")
print("핸드폰 이름의 길이 = ${name?.length}")
print("모델명 = ${name?.substring(6, 6)}")
}
}
'?.' 때문에 가독성을 헤치는 경우가 생긴다. 따라서 lateinit를 사용하여 가독성을 향상한다.
classPhone{
lateinitvar name: String
init {
name = "iphone"
}
funprocess() {
name.plus("13 pro")
print("핸드폰 이름의 길이 = ${name.length}")
print("모델명 = ${name.substring(6, 6)}")
}
}
전체 예시 코드는 다음과 같다.
package kr.co.ki.function
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
classMainActivity : AppCompatActivity() {
overridefunonCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var p = Phone()
Log.d("nullable", "핸드폰 종류는 ${p.name} 입니다")
p.process()
}
}
classPhone{
var name: String? = nullinit {
name = "iphone"
}
funprocess() {
name = name?.plus("13 pro")
Log.d("nullable","핸드폰 이름의 길이 = ${name?.length}")
Log.d("nullable","모델명 = ${name?.substring(6, 12)}")
}
}
fun String.plus(word: String): String {
returnthis + word
}
1.2 lazy
lateinit과 다르게 읽기 전용 변수인 val을 사용하는 지연 초기화이다. 사용법은 다음과 같다.
classCompany{
val person: Person by lazy{ Person() }
init {
// lazy는 선언시에 초기화를 진행하므로 별도의 초기화 과정 필요 X
}
funprocess() {
print("person의 이름은 ${person.name}")
}
}
lazy는 선언 시에 초기화를 하기 때문에 별도의 초기화 과정이 필요 없다.
lazy로 선언된 변수가 최초 호출되는 시점이 by lazy {} 안에 넣은 값으로 초기화가 된다. 즉 위의 코드를 보면 company 클래스가 초기화되더라도 person에 바로 Person()로 초기화되지 않고 process 메서드에서 person.name 이 호출되는 순간 초기화된다.
세컨더리 생성자는 프라이머리 생성자와 다르게 constructor을 클래스 내부로 넣는 것이다. 예시는 다음과 같다.
classPhone{
constructor (model: String) {
Log.d("Class", "생성자로 부터 받은 model의 이름은 ${model} 입니다.")
}
}
세컨더리 생성자는 메소드 오버로딩을 적용하여 여러 개를 중복할 수 있다. 다음과 같다.
classPhone{
constructor (model: String) {
Log.d("Class", "생성자로 부터 받은 model의 이름은 ${model} 입니다.")
}
constructor (model: Int) {
Log.d("Class", "생성자로 부터 받은 model의 번호는 $[model} 입니다.")
}
constructor (model: String, model2: Int) {
Log.d("Class", "생성자로 부터 받은 model의 이름은 ${model} 이고 번호는 ${model2} 입니다.")
}
}
Default 생성자
생성자가 없는 경우 Default 생성자가 되며 파라미터가 없는 프라이머리 생성자와 동일하다.
1.3 클래스의 사용
클래스의 사용은 생성자를 호출하며 사용한다. 파라미터 없이 괄호를 붙이면 생성자가 호출되며 init 블록 안의 코드가 실행된다. 세컨더리 생성자는 init 블록이 먼저 실행되며 constructor 블록 안의 코드가 실행이 된다. 다음과 같이 클래스를 호출한 후 생성된 인스턴스를 변수에 담을 수 있다.
var variable = Class()
예시를 통해 사용법을 보면 다음과 같다. (.) dot 연산자를 통해 클래스 내부의 멤버 함수, 멤버 변수에 접근할 수 있다.
classPhone{
var modelName: String = "Galaxy"funprintName() {
Log.d("Class", "Phone의 이름은 ${modelName} 입니다."_
}
}
var phone = Phone()
phone.modelName = "iphone"
phone.printName()
1.4 Object
자바의 static과 비슷하게 object를 아용하면 생성자로 인스턴스화 하지 않고 사용할 수 있다. 즉 클래스명에 dot 연산자를 이용하여 멤버 변수 및 멤버 함수에 접근이 가능한 것이다. 예시는 다음과 같다.
Object Phone {
var modelName: String = "Galaxy"funprintName() {
Log.d("Class", "Phone의 이름은 ${modelName} 입니다."_
}
}
Phone.modelName = "iphone"
Phone.printName()
단 Object는 한 앱 전체에 한개만 생성될 수 있다.
1.5 Companion Object
companion object를 사용하면 object와 마찬가지로 인스턴스의 생성 없이 사용할 수 있다.
여태까지 로그 출력을 위해 사용했던 Log.d 역시 Log 클래스 안에 object 코드 블록 안에 있기 때문에 바로 클래스명에 dot 연산자를 이용하여 사용할 수 있었다.
1.6 data 클래스
코틀린에서 간단한 값의 저장 용도로 data class를 사용할 수 있다. data 클래스의 형식은 다음과 같다.
data class 클래스 이름(val 파라미터: 파라미터형, val 파라미터2: 파라미터형)
위에서 보이듯 클래스 이름앞에 data class를 붙여야 하고 생성자의 파라미터에 var, val을 사용할 수 있다. 예시는 다음과 같다.
상속을 사용하면 자식 클래스에서 부모 클래스의 멤버 변수, 멤버 함수를 사용할 수 있다. 예시는 다음과 같다.
openclassPhone{
var model: String = "modelName"funcall() {
Log.d("inheritance", "${model} 으로 전화합니다.")
}
}
classSmartPhone: Phone() {
funsmartCall() {
model = "iphone"
call()
}
}
1.8 오버라이딩
오버로딩과 말은 비슷하지만 오버라이딩은 상속에서 메서드를 재정의 하는 것을 의미한다. 만약 위의 예시에서 open class에 있는 call()와 이름이 같게 SmartPhone 클래스에서도 smartCall()를 call()로 변경하면 이것이 바로 오버라이딩 이다. 오버라이드에는 메서드 오버라이드와 프로퍼티 오버라이드가 있으며 이는 각각 다음과 같다.
이 포스팅은 고돈호 님의 이것이 안드로이드다 with 코틀린(한빛미디어)을 기반으로 작성되었습니다.
1.1 for문
일반적인 언어들과 마찬가지로 코틀린 역시 반복문을 지닌다. 먼저 for문을 살펴보자. for문은 다음과 같은 형태로 작성한다.
for (인덱스 in 시작 값... 종료 값) { }
for문에 until, downTo 등을 통해 여러 가지 방법을 적용할 수 있다. 다음의 예시 코드를 통해 파악해보자
package kr.co.ki.collectionmap
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
classMainActivity : AppCompatActivity() {
overridefunonCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 1. 일반적인 반복문 10까지for (i in1..10) {
Log.d("For", "현재 숫자는 ${i}")
}
// 2. until로 마지막 숫자 제거var array = arrayOf("SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT")
for (i in0 until array.size) {
Log.d("For", "현재 요일은 ${array.get(i)} 입니다.")
}
// 3. step을 이용한 건너뛰기for (i in1..10 step 2) {
Log.d("For", "현재 숫자는 ${i}")
}
// 4. down to을 이용한 감소for (i in10 downTo 0) {
Log.d("For", "현재 숫자는 ${i}")
}
// 5. 배열, 컬렉션 사용for (day in array) {
Log.d("For", "현재 요일은 ${day} 입니다.")
}
}
}
출력문은 다음과 같다.
2021-12-19 18:08:01.683 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 1 2021-12-19 18:08:01.683 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 2 2021-12-19 18:08:01.684 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 3 2021-12-19 18:08:01.684 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 4 2021-12-19 18:08:01.684 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 5 2021-12-19 18:08:01.684 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 6 2021-12-19 18:08:01.684 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 7 2021-12-19 18:08:01.684 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 8 2021-12-19 18:08:01.684 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 9 2021-12-19 18:08:01.684 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 10 2021-12-19 18:08:01.684 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 SUN 입니다. 2021-12-19 18:08:01.685 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 MON 입니다. 2021-12-19 18:08:01.685 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 TUE 입니다. 2021-12-19 18:08:01.685 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 WED 입니다. 2021-12-19 18:08:01.685 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 THU 입니다. 2021-12-19 18:08:01.685 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 FRI 입니다. 2021-12-19 18:08:01.685 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 SAT 입니다. 2021-12-19 18:08:01.685 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 1 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 3 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 5 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 7 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 9 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 10 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 9 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 8 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 7 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 6 2021-12-19 18:08:01.686 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 5 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 4 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 3 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 2 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 1 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 숫자는 0 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 SUN 입니다. 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 MON 입니다. 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 TUE 입니다. 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 WED 입니다. 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 THU 입니다. 2021-12-19 18:08:01.687 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 FRI 입니다. 2021-12-19 18:08:01.688 1665-1665/kr.co.ki.collectionmap D/For: 현재 요일은 SAT 입니다.
2.1 while문
For문 이외에도 흔히 반복문으로 사용하는 while 역시 존재한다. For문의 사용법은 다음과 같다.
while (조건식) {
}
while문에는 while, do while문이 존재한다. 이 두 개의 가장 큰 차이점은 do while문은 조건을 만족하지 않으면 실행하지 않는 while문과 달리 무조건 한번 실행한다는 것이다.
package kr.co.ki.collectionmap
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
classMainActivity : AppCompatActivity() {
overridefunonCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var current = 1var until = 12while (current < until) {
Log.d("while", "현재 값은 ${current} 입니다.")
current = current + 1
}
var cnt = 1do {
Log.d("while", "현재 값은 ${cnt} 입니다.")
cnt = cnt + 1
} while (cnt < 1)
}
}
결과는 다음과 같다. 다음의 그림에서 보이듯이 cnt가 1이고 cnt < 1을 조건으로 있음에도 불고하고 do while문이기 때문에 한 번은 돌아가는 것을 확인할 수 있다.
3.1 break & continue
그 밖에 break, continue문등의 제어문이 있다. 각각 루프문 탈출, 다음 반복문으로 이동하는 역할이다.
이 포스팅은 고돈호 님의 이것이 안드로이드다 with 코틀린(한빛미디어)을 기반으로 작성되었습니다.
1.1 배열
배열이란 여러 개의 값을 담을 수 있는 자료형이다. 선언하는 형태는 다음과 같다.
var 변수 = Array(개수)
배열 객체는 자료형에 따라 Int, Double, Char 등의 자료형을 Array뒤에 붙여서 만든다. 각각 다음과 같다.
var IntegerArray = IntArray(5)
var LongArray = LongArray(5)
var CharArray = CharArray(5)
var FloatArray = FloatArray(5)
var DoubleArray = DoubleArray(5)
위의 코드에서 5는 각각 자료형에 따른 공간을 5개 할당하라는 의미이며 이를 표현하면 다음과 같다.
[0]
[1]
[2]
[3]
[4]
즉 다른 언어와 마찬가지로 0번째 인덱스부터 시작하며 n-1까지의 공간을 할당하는 것을 알 수 있다.
1.2 문자 배열에 빈 공간 할당하기
String은 기본 타입이 아니므로 배열에서 String을 자료형으로 사용하기 위해서는 다음과 같이 사용해야 한다.
var stringArray = Array(5, {item->""})
1.3 값으로 배열 공간 할당하기
다음처럼 arrayOf 함수를 사용하여 String을 직접 할당할 수도 있다.
var dayArray = arrayOf("SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT")
1.4 배열에 값 입력하기
1. 다른 언어와 유사한 방법
배열명[인덱스] = 값
2. set 함수를 사용한 방법
배열명. set(인덱스, 값)
1.5 배열에 있는 값 꺼내기
배열에 값을 입력하는 것 과 마찬가지로 인덱스로 접근하는 법과 함수를 이용한 방법이 있다.