본문 바로가기
Jave & Kotlin

Kotlin - 기본 문법 정리

by devLog by Ronnie's 2021. 12. 21.

들어가기 앞서


코틀린이은 2017년도에 안드로이드 공식 언어로 채택된 언어이다. JVM 기반 언어이며 자바와 유사하지만 더 간결한 문법과 다양한 기능을 제공해준다. 현재 주 언어는 자바를 사용하지만 시간이 날때마다 틈틈히 새로운 기술을 익혀보고자 인프런에 코틀린 기본 강의를 듣고 기본 문법을 정리한다. 그리고 자바와는 어떤 차이가 있는지도 더불어 정리한다.

 

 

코틀린 기본문법


 

패키지 정의

- 패키지 정의는 파일 최상단에 위치함(자바와 동일)
- 자바와 다른점은 디렉터리와 패키지를 꼭 일치시키지 않아도 된다.

임포트

- 자바와 똑같음

함수 정의(자바와 많이 다름)

- 함수는 fun 키워드로 정의함
- 제일 마지막에 리턴 타입이 나오고 생략도 가능한 경우도 있다.
- 식으로 표현된 경우는 return을 생략 가능하다.

//형식

fun sum ( 인자1 : 자료형1, 인자2 : 자료형2, ...) : 반환자료형
//블럭으로 표현된 경우
fun sum(a: int, b: int): int {
  return a + b
}
//식으로 표현된 경우 (위와 동일함)
fun sum(a: int, b: int) = a +b

함수 정의 리턴 값이 없는 경우

- Unit(Object)로 리턴을 한다 (자바의 void와 동일하고 Unit은 하나의 Object이다)
- 아무것도 적지 않으면 Unit 생략 가능
// 리턴값이 없는 경우 Unit 선언
fun printKotlin(): Unit {
  println("hello")
}
// 생략하는 경우
fun printKotlin() {
  println("hello")
}

지역 변수 정의

- val : 읽기전용변수 (자바의 final과 유사), 값의 할당이 1회만 가능하다.
- var : 쓰고읽고가능한변수
//val
val a int = 1 // 즉시 할당(초기화)하는 경우
val b =2 // 타입 추론을 통해 int
val c: int // val을 초기화 필요하므로 컴파일 시 오류 발생
c = 3 // 읽기 전용이므로 이렇게 추후의 값을 할당하는 경우도 컴파일 오류
//var
var x = 5
x += 1 // 추후 값 변경 가능함.

 

기본 자료형 - 숫자형

Double / Float / Long / Int / Short / Byte

 

기본 자료형 - 문자형

String / Char

 

문자열 여러줄 표현

- """ 으로 문장의 앞과 뒤를 감싸기만 하면 개행이나 공백을 포함한 모든 문자를 그대로 표현해준다.

 

문자열 템플릿

val msg = "안녕하세요"

println(msg + "!!") -> 자바

println("${msg} !!") -> 코틀린

 

배열

- 배열의 타입은 코틀린에서 Array이다. Array 타입을 충분히 유추가 가능하다면 생략 가능하다.

- 배열의 생성은 arrayOf()라는 함수를 사용하여 생성과 초기화를 한번에 할 수 있다.

val num1 : Array<Int> = arrayOf(1,2,3,4,5)
val num2 = arrayOf(1,2,3,4,5)

 



주석

- 자바와 자바스크립트와 동일함
- // -> 한줄 주석
- /* */ -> 여러 줄 주석
- 블럭 코맨트가 자바와 다르게 중첩을 허용함
/*
    /*   */
*/

문자열 템플릿

- String Interpolation (문자열 보간법)
- 자바에서처럼 스트링빌더나 + 연산자를 통하지 않고 핸들링 가능
var a = 1
// simple name in template:
val s1 = "a is $a"
a = 2
//arbitrary expression in template:
val s2 = "${s1.replace("is", "was")}, but now is $a"

조건문

fun maxOf(a: int, b: int): int {
  if (a > b) {
    return a
  } else {
    return b
  }
}


조건식으로 변경한 조건문
fun maxOf(a: int, b: int) = if (a > b) a else b

nullable(중요!!!)
- 값이 null일 수 있는 경우 타입에 nullable 마크를 명시해야함
fun parseInt(str: String): int? {
// 정수가 아닌 경우 null을 리턴
}
- ?(nullable 마크) 을 적어줘서 null이 리턴될 수 있음을 명시한다.
- ? 을 적지 않고 null을 리턴하는 경우 컴파일시 오류가 난다.
- nullable 타입의 변수를 접근할 때는 반드시 null 체크를 해야한다.
fun printProduct(arg1 : String, arg2: String) {
val x: int? = parseInt(arg1)
val y: int? = parseInt(arg2)

if(x != null && y != null) {
  println(x * y)
} else {
  println("either '$arg1' or '$arg2' is not a number")
}
}
- 이렇게 nullable을 지원하므로 안전하게 코딩이 가능

자동 타입 변환
- 타입 체크만 해도 자동으로 타입 변환이 됨
- Any는 자바에서의 Object와 같이 최상위 타입이다.
fun getStringLength(obj: Any): int? {
  if(obj is String) { // 여기서 is는 instanceOf와 비슷하다. 타입 비교시 이용
  //'obj'가 자동으로 String 타입으로 변환 됨
  return obj.length
}
  return null
}

while loop
- 자바와 같다고 봐도 됨
val items = listOf("apple", "banana", "kiwi")
var index = 0
while (index < items.size) {
println("item at $index is ${items[index]}")
index++
}

when expression
- 자바의 switch case와 비슷해 보이지만 좀 더 많은 타입을 지원함
- 자바에서는 정수나 스트링 정도 이지만 when에서는 많은 타입 지원
fun describe(obj: Any): String =
when (obj) {
1 -> "One" // obj가 1이면 One
"Hello" -> "Greeting" // Hello 이면 Greeting ...
is Long  -> "Long"
!is String -> "Not a string"
else  -> "Unknown"
}
- 이것을 자바로 동일하게 구현한다면 훨씬 코드가 길어지고 복잡해 질것이다.

ranges

- in 연산자를 이용해서 숫자 범위를 체크 가능
val x = 3
if (x in 1..10) { // 1~10까지 범위를 in 을 통해 줄 수 있다. -> 1과 10사이에 3이 있다면 참
println("hello")
}
- range를 이용한 for loop
for (x in 1..5) { // 1~5까지 반복
print(x)
}

 

for 반복문 - 숫자 반복하기

- 1..10까지의 합 구하기

var sum = 0
for (i in 1..10) {
    sum += i
}

- 1..10 사이에서 홀수의 합을 구하기

var sum = 0
for (i in 1..10 step 2) {
    sum += i
}

- 10 ~ 0 까지 3씩 감소하면서 출력하기

for (i in 10 downTo 0 step 3) {
    println("i is ${i},,")
}

 


Collections

- 컬렉션도 in 으로 loop 가능
- foreach 와 동일함
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
- in으로 해당 값이 collection에 포함되는지 체크 가능
val items = setOf("apple", "banana", "kiwi")
when {
"orange" in items -> println("juicy") // items 에 orange가 포함되는지 체크하는 것
"apple" in items -> println("apple is fine too")
}
- 람다식을 이용해서 컬렉션에 filter, map 등의 연산 가능 (자바의 stream과 비슷)
val fruits = listOf("banana", "avocado", "apple", "kiwi")
fruits
.filter{ it startsWith("a") } // 여기서 it 이란 list에 있는 값들이 들어오는 변수
.sortedBy { it }
.map { it.toUpperCase() }
.forEach { println(it) }

 

접근제한자
- public

- private

- internal : 같은 모듈 내에서만 사용 가능

ex ) app 모듈 내에 tv, phone, watch 모듈이 있고, app 모듈 내에 Fruit 클래스 내에 internal로 선언한 필드 weight이 있다면, tv, phone, watch 모듈에서 모두 weight 필드에 접근 가능하다.

- protected : 상속받은 클래스에서 사용할 수 있다.

 

클래스 상속

- 코틀린에서 클래스는 기본적으로 상속이 금지

- 상속을 가능하도록 허용하려면 open 키워드를 클래스 선언 앞에 추가해야함.

open class Fruit{}
class Apple : Fruit() {}

 

내부 클래스

- 다른 언어들에서와 같이 클래스 내부에 클래스를 선언하는 것을 내부클래스라고 함

- 내부 클래스 선언시 inner 키워드를 사용

class Student {
    var name : String = "Jordan"

    init{
        println("My name is $name")
    }

    inner class Personality {
        fun doSomething() : Unit {
            name += ", He is Chicago Bulls No.23 Basketball Start"
            println(name)
        }
    }
}

val student : Student = Student()
student.Personality().doSomething()

 

추상클래스

 

 

 

 

 

 

댓글