[include(틀:상위 문서, top1=Kotlin)] [include(틀:문자 입력시 주의, c1=\\0, c2=\\\\0)] [include(틀:프로그래밍 언어 문법)] [목차] [[분류:프로그래밍 언어 문법]] == 개요 == [[Kotlin]](코틀린)의 문법을 설명하는 문서다. == 기본 == 코틀린의 코드는 객체 지향을 원칙으로 하며, [[Java|자바]]와 '''100% 연계되는 문법'''을 사용하고 있다.[* 실제로 안드로이드 스튜디오 등에서 자바 코드를 넣으면 자동으로 코틀린으로 변환해 준다.] .kt 또는 .kts의 저장 형식을 가진다. 위에서도 서술 했듯이 자바와 굉장히 비슷한 문법 구조를 가지고 있어 자바를 한번 배워 본 사람이라면 코틀린을 어렵지 않게 배울 수 있다. 또한 코드가 '''매우 간결하여''' 쉽게 배울 수 있다. 그럼에도 불구하고 [[안드로이드(운영체제)|안드로이드]] 앱을 만들 때도 기능상의 제한이 없다. 함수 선언 방법 또한 자바와 동일하다. == 편집 지침 == 소스 코드로 예시를 들 때 ||\{{{#!syntax java (소스코드) }}}|| 문법을 활용하여 소스코드를 써 주시기 바랍니다. 코틀린 전용은 지원하지 않습니다. 또한 메인함수에는 통일을 위해 '''array 대신 args를 사용하시기 바랍니다.''' 예시: {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { println("Hello world!") } }}} == 메인 메서드 == {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { // TODO } }}} 코틀린의 경우에는 메인메서드의 길이가 상당히 짧다. [[C언어]], [[Java|자바]]등과 비교하면 짧다는거지 메인함수가 없는 [[Python|파이썬]]과 비교하면 곤란하다. 당장 패키지명만 선언하고 메인함수를 작성한 뒤 바로 코딩에 들어가도 무방하다. '''args''' 와 '''array''' 둘 다 사용법은 같다. 똑같이 작동하지만 JDK 환경인지, Native로 작동하는지 등에 따라서 다르다. [[Kotlin]] 1.3 버전부터는 args를 붙일 필요는 없게 됐다. == 타입 == * 숫자(정수): Long[* Int보다 큰 수 입출력 가능] > Int[* 8자리까지 입출력 가능] > Short[* Int보다 작은 수 입출력 가능] > Byte [* Short보다 작은 수 입출력 가능] * 숫자(실수): Double[* 나눗셈등을 할때 요긴하게 사용된다.] > Float[* 많이 쓰지는 않는다.] * 문자: Char[* 한 글자 입출력 가능] * 문자열: String[* 문자열 입력에 제한이 없다.] == 변수 선언 == {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { var a1: Int = 1 var a2 = 1 var b: String = "1" val c: Double = 3.141592 println(a1) // OK println(b) // OK println(c) // OK a1 = a1 ++ // OK b = b + "2" // OK c = c ++ // ERROR } }}} 타입을 적어줘도, 적어주지 않아도 된다. var이 아니라 val로 쓰게 된다면 c = c ++과 같이 그 값을 바꾸지 못한다. 기본적으로는 val을 쓰는게 좋은 습관이지만, 어차피 대부분 var로 바꿀거 var로 코딩 하는 사람도 적지 않다. === 특이한 경우: null check === {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { var a: Int? = 1 var b: Int? = 1 println(a !! + b !!) var c: Int? = null // OK var d: Int = null // ERROR } }}} 기본적으로 ?를 타입 뒤에 붙이면 null을 사용할 수 있다. 하지만 둘 다 null 선언이 된 상태에서 값을 수정하거나 출력하려 하면 null check 에러가 뜨는 경우가 있다. 이런 경우에는 !!를 붙여주면 해결되는 경우도 있다. === 특이한 경우: 형변환 하기 === {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { var a: Int = 1 var b: String = 1 println(a + b) // ERROR println(a + b.toInt()) // OK var c: Int = 1 var d: String = 1 println(c + d!!.toInt()) // OK } }}} String과 Int를 더하려면 오류가 나기 때문에 '''.to타입()'''을 붙여 타입을 변경할 수 있다. null check를 하는 경우 '''d!!.toInt()'''로 해주면 된다. == 함수 == {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { // TODO var Method: Method = Method Method.Method1() // ERROR Method.Method2() // OK } class Method() { fun Method1() { println("Hello") } open fun Method2() { println("Hello") } } }}} 함수를 쓸 때 앞에 open을 붙여줘야 다른 곳에서도 똑같이 사용할 수 있다. open을 붙이지 않는다면 val같이 읽기 전용으로만 이용 할 수가 있다. 함수에 대한 기본개념이 있다면 어떻게 사용하는지 문법만 배우면 된다. Method1과 Method2를 class Method로 감싸줬는데 이를 사용하기 위해서는 '''var Method: Method = Method'''로 그것을 쓸 함수에 선언을 해주어야한다. 참고로 Method라는 클래스의 타입은 그대로 Method가 된다. 계속 Method라는 얘기가 나오는데 '''클래스의 이름을 Method로 할 필요는 없다.''' --어떤 컴파일러에서는 함수명으로 한글도 지원된다.-- === 확장 함수 === 이미 선언되어있는 객체나 클래스 하위의 함수를 재정의하거나 새로 정의할 수도 있다. {{{#!syntax java package HelloWorld fun String.sayHello() { println("Hello, $this") // this는 객체 String을 가리킴 } fun main(args: Array<String>) { "NamuWiki".sayHello() // "Hello, NamuWiki" 출력 } }}} == 입력 받기 == === Bufferreader === === Scanner === == 출력하기 == === 문자 === {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { // 1 print("안녕") println("하세요") // 2 var Hello: String = "안녕하세요" println(Hello) // 3 // 4 var World1 : String = "안녕" var World2 : String = "하세요" println("${World1 + World2}") println(World1 + World2) } }}} 네가지 경우 모두 '''안녕하세요'''가 출력된다. print인 경우는 줄바꿈을 하지 않는다. C언어를 예로 들자면 ''' printf("hello world!\\n");''' 에서 \\n이 생략된 격이다. 이 말은 즉슨 println의 경우에는 \\n이 자동으로 삽입되어 있다는 뜻이다. --\\n = ln ?-- 물론 \\n 사용이 불가능 한 것은 아니다. 다만 println이 쓰이는데 \\n까지 같이 쓴다면 두줄 줄 바꿈이 된다. === 숫자 === == 배열 == === Array === Array를 만들 때는 이와 같이 하면 된다 {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { val doubleArray: Array<Double> = arrayOf(1.0, 1.5, 2.0, 3.0) } }}} 위의 경우 arrayOf 안에 있는 값을 가져가서 Array가 그 값들의 type을 가지게 된다. === List === == 반복문 == === for문 === {{{#!syntax java package HelloWorld fun main (args: Array<String>) { for (i in 0 .. 5) { println("안녕하세요") } for (i in 1 .. 6) { println("안녕하세요") } for (i in 1 until break) { println("안녕하세요") } } }}} 첫번째와 두번째 경우 둘 다 안녕하세요가 5번 출력된다. 반쯤 람다식이라고 볼 수 있는데, 기존 [[Java]]와 절차지향 언어인 [[C언어]]에서 쓰였던 var i = 0; i > 10; i ++ 같은 문법 대신 눈물나게 간결한 문법을 제공한다. 세번째 경우인 until의 경우에는 저 자체로는 굉장히 불완전한 코드이다. until을 이용해서 break까지, 변수 a의 값이 5가 될때 까지등 여러가지 조건을 내걸어 반복문을 사용 할 수 있다. 이중 반복문을 사용하려는 경우 첫번째 반복문에 변수로 i를 지정해주었다면 두번째 반복문에는 i를 사용하면 안된다. 코드 안에서 내부적으로 i를 여러번 반복하고 그 반복 안에 새로운 i가 있는 형식이기 때문이다. 여러 IDE에서 실행을 해보면 빨간색 밑줄 또는 노란색 밑줄이 그어지면서 this variable is alreadt defined같은 오류가 뜬다. === while문 === == 제어문 == === if[else] === {{{if (expression) statement1 [else statement2]}}} () 속의 조건식(expression)이 참이 되면 statement1을, 거짓이면 statement2를 실행하는 [[구조]]로 되어 있다. else 이하는 생략 가능하며 else 뒤에 if를 다시 사용하여 if ... else if ... else if ... else 와 같이 사용할 수도 있다. {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { var a = 1 var b = 1 if(a == b) { // TODO } else { // TODO } } }}} === when === [[Java|자바]]의 [[C언어/문법#switch ... case ...|switch 문]]이랑 비슷하지만 더 많은 [[기능]]을 가졌다. {{{#!syntax java package HelloWorld; fun main(args: Array<String>) { var a = 1 when(a) { 1 -> println("a는 1입니다") 5 -> println("a는 5입니다") 7, 9 -> println("a는 7 아니면 9입니다") in 10..100 -> println("a는 10에서 100까지 중에 있습니다") else -> println("a는 그 외입니다") } } }}} == 상속 == 한 객체가 다른 객체를 상속할 때에는 다음과 같은 형태를 띈다. {{{#!syntax java package kotlin class ParentClass() class ChildClass: ParentClass() }}} 한 객체가 인터페이스를 구현할 때에는 다음과 같은 형태를 띈다. {{{#!syntax java package kotlin interface SampleInterface() class ChildClass: SampleInterface }}} == 람다식 == === 고차함수 === 코틀린은 인터페이스를 통해서 함수를 인자로 넘겨주던 Java와 다르게 아주 간편하게 함수를 주고받거나 반환할 수 있다. * 함수를 인자로 받기 {{{#!syntax java package Kotlin fun printer(a: Int, b: Int, f: (Int, Int) -> Int) { println("$a 와 $b 를 함수에 -> ${f(a, b)}") } }}} * 함수를 반환하기 {{{#!syntax java package Kotlin fun getPrintingFunction(str: String): () -> Unit { return { println(str) } } }}} 또한, 함수(람다식)을 인자로 넘겨주는 함수를 사용할 경우, 함수의 내용을 소괄호 밖에 표시하는것이 권장된다. {{{#!syntax java printer(3, 5, {i, j -> i + j}) // 작동 printer(3, 5) {i, j -> i + j } // 작동 }}} 이와 앞서 언급한 클래스 내 함수 삽입을 이용하면 context를 만들 수 있다. {{{#!syntax java package HelloWorld; object NamuWiki { fun getDocument(name: String): String { // TODO } } fun <T> namuWiki(lambda: NamuWiki.() -> T) : T { // lambda는 Namuwiki 하위 함수 return NamuWiki.lambda() } fun main(args: Array<String>) { val kotlin: String = namuWiki { // returns result of getDocuent() getDocument("Kotlin/문법") // getDocument under context namuWiki } getDocument("Kotlin/문법") // ERROR: function getDocument doesn't exist println(kotlin) } }}}