본문 바로가기
📁App Developing/Kotlin 강좌

kotlin 기초 문법

by Hush 2022. 7. 23.

변수의 선언

var a : String = "asdf"
val a : String = "qwer"

var로 변수를, val로 상수를 선언할 수 있다.

변수명 뒤에 콜론을 적고 자료형을 적어줄 수 있다. 적지 않더라도 형추론을 통해 변수의 자료형을 결정해준다.

 

변수에 지정된 자료형과 일치하지 않는 값을 대입할 수 없다.

 

 

함수

fun 함수명(인수1 : 자료형1, 인수2 : 자료형2, ... ) : 반환자료형{
	//함수 내용
}

반환값이 없다면 Unit형을 사용한다. 이는 자바의 void에 대응한다.

 

 

자료형

코틀린의 기본 자료형은 모두 객체이다.

 

숫자형

코틀린에서 숫자를 표현하는 자료형은 Double, Float, Long, Int, Short, Byte 등을 사용할 수 있다.

리터럴이란 자료형을 알 수 있는 표기 방식을 말한다. 리터럴에 따라 코틀린 컴파일러는 자료형을 추론한다.

val a = 10 // Int
val b = 10L // Long
val c = 10.0 // Double
val d = 10.0f // Float

 

문자형

코틀린에서 문자를 나타내는 자료형은 두 가지이다. Char와 String이다. Char가 숫자형이 아니라는 점이 자바와 다르다.

String의 리터럴은 큰따옴표이고, Char의 리터럴은 작은따옴표로 자바와 같다.

  • 여러 줄에 걸쳐 문자열을 표현할때는 파이썬처럼 큰따옴표 세개를 리터럴로 사용한다.
  • 문자열의 동일 여부를 == 로 판단할 수 있다.
  • + 기호로 문자열을 연결할 수 있으며, $기로를 사용하면 문자열 리터럴 내부에 변수를 쉽게 포함할 수 있다.
val str = "안녕"

println("$str 하세요") // 안녕하세요

 

배열

배열은 Array 라는 별도의 타입으로 표현한다.

arrayOf() 메서드를 사용해서 배열의 생성과 초기화를 함께 생성한다.

배열에 요소에 접근하는 것은 자바나 파이썬처럼 대괄호에 요소 번호를 지정하는 방식이다.

val numbers: Array<int> = arrayOf(1, 2, 3, 4, 5)
val numbers2 = arrayOf(1, 2, 3, 4, 5) // 자료형 생략

numbers[0] = 5 // [5, 2, 3, 4, 5]

 

제어문

제어문은 크게 if, when, for, while의 4가지로 나뉜다.

if 문은 C와 비슷하게 생겼다.

var a: Int = 0
if (a == 0) println("zero")
if (a == 0) {
	println("zero")
} else {
	println("not zero")
}

다음과 같이 if문을 식처럼 사용할 수도 있다.

val max = if(a > b) a else b

when문은 switch문과 비슷하다. 근데 더 강력한 기능들을 제공한다.

when(x) {
	1 -> println("x == 1")
    2, 3 -> println("x == 2 or x == 3")
    in 4..7 -> println("4부터 7 사이")
    !in 8..10 -> println("8부터 10사이가 아님")
    else -> {
    	print("x 는 1이나 2가 아님")
    }
}

when문 또한 식처럼 사용할 수 있다.

val numStr = when(number % 2){
	0 -> "짝"
    else -> "홀"
}

 

when문의 결과를 함수의 반환값으로 사용할 수도 있다...

fun isEven(num:Int) = when (num % 2) {
	0 -> "짝"
    else -> "홀"
}

for문은 파이썬과 비슷하다.

배열이나 컬렉션을 순회하는 방식이다.

val numbers = arrayOf(1, 2, 3, 4, 5)

for (num in numbers){
	println(num)
}

기본적인 순회 방식 외에도 다양한 사용 방법이 있다.

증가 범위는 .. 연산자를 사용할 수 있다.

감소 범위는 downTo 키워드를 이용해서 step 키워드로 증감의 간격을 조절할 수 있다.

//1~3까지 출력
for (i in 1..3){
    println(i)
}

//0~10까지 2씩 증가하며 출력
for (i in 0..10 step 2){
    println(i)
}

//10부터 0까지 2씩 감소하며 출력
for (i in 10 downTo 0 step 2){
    println(i)
}

 

while 문은 주어진 조건이 참일 떄 반복하는 문법이다.

do while문도 존재한다.

var x = 10
while (x>0){
    x--
    println(x)
}

var y = 10
do{
    y--
    println(y)
}while (y > 0)

 

클래스

클래스의 선언과 생성자의 표현은 다음과 같다.

class Person{
    constructor(name: String) {
        println(name)
    }
}

프로퍼티에 접근할때는 파이썬처럼 점을 찍고 프로퍼티 이름을 적어주면 된다.

class Person(var name: String){

}

val person = Person("멋쟁이")
person.name = "키다리"
println(person.name)

 

접근 제한자라는 개념이 있는데, 접근 제한자란 변수에 접근을 통제하는 기능을 한다.

  • public (생략 가능): 전체 공개.
  • private: 현재 파일 내부에서만 사용할 수 있다.
  • internal: 같은 모듈 내에서만 사용할 수 있다.
  • protected: 상속받은 클래스에서 사용할 수 있다.
class A{
    val a = 1 // public
    private val b = 3
    protected val c = 3
    internal val d = 4
}

 

코틀린에서의 클래스는 기본적으로 상속이 금지된다.

상속이 가능하게 하려면 open 키워드를 클래스 선언 앞에 추가한다.

open class Animal {
    
}

class Dog : Animal() {
    
}

 

 

null

코틀린은 기본적으로 객체를 불변으로 보고 null값을 허용하지 않는다. null값을 허용하려면 별도의 연산자가 필요하고, null을 허용한 자료형을 사용할 때도 별도의 연산자들을 사용하여 안전하게 호출해야 한다.

null 허용

코틀린에서는 null값을 허용하지 않으므로 모든 객체는 생성과 동시에 값을 대입하여 초기화해야 한다.

즉, 다음 코드는 에러가 발생한다.

val a : String

코틀린에서 null값을 허용하려면 자료형의 오른쪽에 ? 기호를 붙여주면 된다.

다음 코드는 null값을 허용하는 String객체이기 때문에 에러가 발생하지 않는다.

val a : String? = null

 

 

선언과 초기화의 분리

안드로이드를 개발하다 보면 선언만 미리 해두고 초기화를 나중에 할 경우가 있다.

이때는 lateinit 키워드를 변수 선언 앞에 추가하면 된다.

안드로이드에서는 특정 타이밍에 객체를 초기화할 때 사용한다.

초기화를 잊는다면 잘못된 null값을 참조하여 앱이 종료될 수 있으니 주의해야 한다.

lateinit var a : String

a = "hello"
println(a)

lateinit은 다음 조건에서만 사용할 수 있다.

  • var 변수에서만 사용한다.
  • null값으로 초기화할 수 없다.
  • 초기화 전에는 변수를 사용할 수 없다.
  • int, Long, Double, Float에서는 사용할 수 없다.

lateinit이 var로 선언한 변수의 늦은 초기화라면, lazy는 val로 선언한 상수에 늦은 초기화를 할 수 있다.

val 선언 뒤에 by lazy 블록에 초기화에 필요한 코드를 작성한다.

마지막 줄에는 초기화할 값을 작성한다.

str이 처음 호출될 때 초기화 블록의 코드가 실행된다.

println() 메서드로 두 번 호출하면 처음에만 "초기화"가 출력된다.

lazy로 늦은 초기화를 하면 앱이 시작될 때 연산을 분산시기킬 수 있어 빠른 실행에 도움이 된다.

lazy는 val로 선언되는 상수라면 추가적인 조건 없이 사용할 수 있다.

 

null을 취급하는 연산자

변수 뒤에 !!를 추가하면 null값이 아님을 보증하게 된다.

다음과 같이 null값이 허용되는 name 변수의 경우 String? 타입이기 때문에 String 타입으로 변환하려면 !!를 붙여서 null이 아님을 보증해야 한다.

val name: String? = "키다리"

val name2: String = name // Error
val name3: String? = name // OK
val name4: String = name!! // OK

 

메서드 호출시 점 연산자 대신 ?. 연산자를 사용하면 null값이 아닌 경우에만 호출된다. 즉, 안전한 호출이 가능해진다.

다음 코드는 str 변수의 값이 null 값이 아니라면 대문자로 변경하고, null값이라면 null을 반환한다.

val str: String? = null
var upperCase = if (str != null) str else null // null
upperCase = str?.toUpperCase() // null

안전한 호출 시 null이 아닌 기본값응ㄹ 반환하고 싶을 때에는 엘비스 연산자(?:)를 함께 사용한다.

마지막 코드는 이제 null이 아닌 "초기화하시오"라는 문자열을 반환한다.

val str: String? = null
var upperCase = if (str != null) str else null // null
upperCase = str?.toUpperCase() ?: "초기화하시오" // null

 

컬렉션

컬렉션은 개발에 유용한 자료구조를 말한다.

안드로이드 개발에서도 리스트나 맵은 자주 사용되는 자료구조이다.

 

리스트

리스트는 배열처럼 같은 자료형의 데이터들을 순서대로 가지고 있는 자료구조이다.

중복된 아이템을 가질 수 있고 추가, 삭제, 교체 등이 쉽다.

 

요소를 변경할 수 없는 읽기 전용 리스트는 listOf() 메서드로 작성할 수 있다.

val foods: List<String> = listOf("라면", "갈비", "밥")

형추론으로 자료형을 생략할 수 있다.

val foods = listOf("라면", "갈비", "밥")

요소를 변경하는 리스트를 작성할 때는 mutableListOf() 메서드를 사용한다.

 

맵은 키와 값의 쌍으로 이루어진, 키가 중복될 수 없는 자료구조이다.(파이썬의 리스트?!)

리스트와 마찬가지로 mapOf() 메서드로 읽기 전용 맵을 만들 수 있고, mutableMapOf() 메서드로 수정이 가능한 맵을 만들 수 있다.

맵의 요소에 접근할 때는 대괄호 안에 키를 요소명으로 작성하여 접근한다.

 

집합

집합은 중복되지 않은 요소들로 구성된 자료구조이다.

 setOf() 메서드로 읽기 전용 집합을, mutableSetOf() 메서드로 수정 가능한 집합을 생성한다.

집합은 이 책의 예제에서는 사용하지 않지만 리스트, 맵과 함께 대표적인 기본 자료구조이다.

 

람다식

람다식은 하나의 함수를 표현하는 방법으로 익명 클래스나 익명 함수를 간결하게 표현할 수 있어서 매우 유용하다.

코드를 간결하게 해주지만 디버깅이 어렵고 남발할 경우 오히려 코드 가독성이 떨어지니 주의하자.

두 수를 더하는 함수를 다음과 같이 표현할 수 있다.

 

 

 

 

 

 

TODO# 인터페이스

TODO# SAM 변환

TODO# 기타 기능

 

 

 

'📁App Developing > Kotlin 강좌' 카테고리의 다른 글

스탑워치 메모  (0) 2022.07.25
Bmi 앱 메모  (0) 2022.07.24
kt 파일에서 xml 파일의 요소에 접근하기  (0) 2022.07.23
명언 앱 만들기  (0) 2022.07.22
주사위 앱 만들기  (0) 2022.07.21

댓글