이번 포스팅에서는 Kotline 의 기본 제어문(반복문/조건문) 사용법을 알아보도록 하겠습니다.
모든 언어들이 비슷하기 때문에 하나의 언어만 잘 알아두면 나머지 언어의 문법도 금방금방 익힐 수 있는 것 같습니다.
Kotline 의 제어문도 다른 언어들과 비슷 하지만, 함축적으로 사용되는 부분이 있어 다른 언어들과는 다르게 Kotline 의 문법을 모르면 잘 알아보기가 힘들게 되어 있는 부분도 있습니다.
익숙해 지면 다른 언어들보다 편할것이라는 생각도 드네요. ^^
1. If 문
Kotline 에서 if 문은 Expression 입니다. 즉, value 를 return 합니다. if 문 자체로 기존의 3항 연산자의 역할을 대체하기 때문에 더이상 삼항 연산자는 사용되지 않습니다. (조건 ? true : false)
기존 우리는 if 문을 아래와 같이 사용했습니다.
max 에 a 변수를 넣고, 만약 a 보다 b 가 크다면 max 변수에 b 의 값을 넣는 코드입니다.
// Traditional usage varmax=aif (a<b) max=b// With else varmax: Intif (a>b) {
max=a
} else {
max=b
}
Kotline 에서는 위의 if 문을 아래와 같이 간단하게 사용할 수 있습니다.
// As expression valmax=if (a>b) aelseb
즉, " if (a>b) a else b " 구문 자체가 a 혹은 b 의 값을 return 하기 때문에, max 변수에 바로 이 값을 대입할 수 있습니다.
만약, if 문 자체에 블럭이 포함되어야 한다면 위 구문은 아래와 같이 사용할 수 있습니다.
valmax=if (a>b) {
print("Choose a")
a
} else {
print("Choose b")
b
}
위의 경우 블럭의 끝에 쓰여진 값이 return 되는 값이 됩니다.
2. When
When 은 일반 언어에서 사용되던 Switch 문을 대체합니다.
when (x) {
1->print("x == 1")
2->print("x == 2")
else-> { // Note the blockprint("x is neither 1 nor 2")
}
}
When 옆에 쓰여진 x 에 값이, 블럭 안의 조건에 충족이 될 때 까지 모든 인수를 순차적으로 검사 합니다.
아무 조건에도 충족되지 않으면 else 분기문으로 들어가게 되고, Switch 문의 default 문은 필수가 아니지만, When 의 else 문은 필수로 들어가야 합니다.
많은 경우가 동일한 방식으로 처리되어야 하는 경우에는 . (콤마) 를 사용하여 조건을 추가할 수 있습니다.
when (x) {
0, 1->print("x == 0 or x == 1")
else->print("otherwise")
}
각 조건의 경우에는 위와 같이 특정 상수 값 (0, 1) 이 올 수도 있지만, 함수가 올 수도 있습니다.
when (x) {
parseInt(s) ->print("s encodes x")
else->print("s does not encode x")
}
위의 경우에는 x 와 parseInt() 에서 return 되는 값과 일치하게 되면 "s encodes x" 를 출력할 것입니다.
그리고 in 키워드를 사용하여 특정 값의 범위를 지정 할 수도 있습니다.
when (x) {
in1..10->print("x is in the range")
invalidNumbers->print("x is valid")
!in10..20->print("x is outside the range")
else->print("none of the above")
}
in 1..10 은 1<= x <=10 의 범위를 의미 합니다. Range 에 대해서는 'https://kotlinlang.org/docs/reference/ranges.html' 를 참고해 보세요 .
마지막으로 when 을 사용할 때 인수를 생략할 수 있습니다.
인수를 생략하게 되면 분기 조건은 단순히 bool 식이 되고, 해당 조건이 참일 때 분기문이 실행 됩니다.
아래의 경우에서는 x 가 홀수 일 경우 "x is odd", 짝수일 경우 'x is even" 둘다 아닐 경우에 "x is funny" 가 출력 됩니다.
when {
x.isOdd() ->print("x is odd")
x.isEven() ->print("x is even")
else->print("x is funny")
}
3. For Loops
for loop 는 비교적 기존에 사용하던 for 문과 크게 다르지 않습니다. iterator 를 제공하는 모든 것들을 반복할 수 있습니다.
아래 예제에서는 item 에 collection 에 있는 모든 값들이 하나씩 대입이 되면서 반복 하게 됩니다.
for (itemincollection) print(item)
배열이나 리스트를 반복할 경우에 index 를 사용하고 싶다면 indices를 사용 합니다.
for (iinarray.indices) {
print(array[i])
}
혹은 withIndex' fun 을 사용해서 index 와 value 를 return 받아 for문을 돌릴 수도 있습니다.
for ((index, value) inarray.withIndex()) {
println("the element at $index is $value")
}
4. While Loops
while 문과 do.. while 문은 java 와 완전히 동일합니다.
아래의 예제에서 do 블록 안에 정의한 멤버변수 y 는 while 의 조건 식에서 참조할 수 있습니다.
while (x>0) {
x--
}
do {
valy=retrieveData()
} while (y!=null) // y is visible here!
여기까지 Kotline 의 if, when, for, while 제어문 사용법에 대해 간단히 알아보았습니다.
기본 문법이기 때문에 잘 익혀두면 Kotline 으로 코딩하는데 많은 도움이 될 것입니다.
Parameter 의 전달은 name: type 과 같이 사용하며, default value 를 가질 수 있습니다. 인자가 전달되지 않으면 default value 가 값에 사용되며 불필요한 함수 오버로딩을 막을 수 있습니다.
checkCustomer("Gildong") 와 같이 필요한 인자만 사용하여 함수 호출이 가능합니다.
fun checkCustomer(name: String, phone: String = "NA", age: Int = 30){
...
}
checkCustomer("Gildong") // The default value phone = "NA" age = 30 is used
오버라이딩은 상위 메소드와 동일한 인자를 가지게 되므로, default value 를 사용하지 않을 때는 오버라이딩을 하여 default value 를 선언하지 않아야 합니다.
open class A { open fun foo(i: Int = 10) {...}
}
class B: A(){
override fun foo(i: Int) {...} // no default value allowed
}
Name Arguments
함수를 호출할 때 parameter 의 이름을 사용하는데, 이를 Name Argument 라고 부릅니다.
단, str 인자가 positional argument 라 부르는데, positional argument는 항상 Name argument 보다 앞에 있어야 합니다.
즉, f(1, y = 2)는 가능하지만 f(x = 1, 2) 는 불가능합니다.
Unit-returning Functions
함수에서 return 값이 불필요하다면 return type을 Unit 으로 선언할 수 있습니다. Unit 은 명시적으로 반환할 필요가 없습니다.
return Unit 이나 return 은 선택적으로 할 수 있습니다. 또한 Unit 은 생략 가능합니다.(반환값을 사용하지 않는다면 Unit 이 생략되어 있는것과 같습니다.)
fun printHello(name: String?): Unit {
if (name != null)
println("Hello ${name}")
else
println("Hi there")
}
Single-Expression functions
함수가 한줄로 표현 가능하다면 괄호는 생략 가능합니다. 또한 반환값도 컴파일러에 의해 유추될 수 있다면 생략 가능합니다.
fun double(x: Int): Int = x * 2
fun double(x: Int) = x * 2
Variable number of arguments(Varargs)
함수의 매개 변수는 vararg modifier로 표시될 수 있습니다.
fun <T> asList(vararg ts: T): List<T> {
val result = ArrayList<T>()
for(t in ts) // ts is an Array
result.add(t)
return result
}
val list = asList(1, 2, 3)
asList 함수에서 T형의 vararg 매개 변수가 T의 배열로 표시됩니다. 하나의 매개 변수만 vararg로 표시 될 수 있습니다.
Java 와의 호환성이 Kotlin 의 큰 장점으로 부곽되는 만큼 Java 와 비교하게 되는 부분이 있습니다.
Kotlin 에서 Class는 Java와 같이 아래처럼 사용합니다.
class Person{ }
그러나 Java 와 다르게 Body 가 없이 아래와 같이 사용될 수도 있습니다.
class Person
Kotlin에서는 primary constructor 과 하나 이상의 secondary constructor 를 가질 수 있습니다.
primary constructor 는 class 선언시 함께 가능합니다.
constructor 키워드는 생략 가능합니다.
annotation 이나 접근자(private, pubilc 등) 와 함께 사용되는 경우 생략할 수 없습니다.
class Person constructor(firstName: String) {
}
class Person(firstName: String) {
}
primary constructor
primary constructor 는 어떤 코드도 포함하지 않으므로 initializer block 을 사용하여 초기화 코드를 구현하면 됩니다.
constructor 가 불리면 객체 생성이 되면서 initializer block 이 불립니다.
primary constructor 의 parameter 는 class 내 어디서든(init 블럭이나 속성값 초기화) 사용 가능합니다.
class Person(name: String) {
val nameInfo = "Name : $name".also(::println)
init {
println("First initializer block that prints ${name}")
}
val secondProperty = "Second property: ${name.length}".also(::println)
init {
println("Second initializer block that prints ${name.length}")
}
}
secondary constructor
constructor 키워드가 반드시 사용되어야 합니다.
class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}
primary constructor 가 있는 경우 모든 second constructor는 primary constructor 에게 위임해야 합니다. 동일 클래스 내에서 다른 생성자로의 위임은 this 키워드를 사용합니다.
initializer block의 코드는 primary constructor 의 일부가 된다. primary constructor 로의 위임은 secondary constructor 코드 실행 전에 실행되므로 모든 initializer block 의 코드는 가장 먼저 실행됩니다.
class Constructors {
init {
println("Init block") // 먼저 실행됨
}
constructor(i: Int) {
println("Constructor") // 나중에 실행됨
}
}
class의 instance 생성하기
class의 instance 를 생성하는데 JAVA에서는 new 키워드를 사용했다면, Kotlin 에서는 constructor 호출만 하면 됩니다.
val invoice = Invoice()
val customer = Customer("Joe Smith")
class 상속받기
Kotlin 에서 class 를 상속받기 위해서는 아래와 같이 사용할 수 있습니다.
C++과 같이 : 기호를 사용하는데 super class의 클래스명에 괄호기호가 붙는 점이 다르네요
물론 함수 override 도 아래와 같이 할 수 있습니다.
open annotation은 class로부터의 상속이 가능하다는 의미입니다. Kotlin에서는 모든 class가 default로 final 로 선언됩니다
open annotation을 사용하는 경우에만 상속이 가능합니다.
method 의 경우에도 open annotation이 있는 method 만 override 가능합니다.
open class Base {
open fun v() {}
fun nv() {}
}
class Derived() : Base() {
override fun v() {}
}
변수의 경우 val 변수(Read only) 를 var 변수로 재정의 할 수 있지만, 반대는 안됩니다.
interface Foo {
val count: Int
}
class Bar1(override val count: Int) : Foo
class Bar2 : Foo {
override var count: Int = 0
}
지난 2017년 5월 Google I/O 에서 Kotlin이 안드로이드의 공식 개발 언어로 발표되었습니다.
Kotlin 공식 사이트를 보면 아래와 같이 메인에서 소개하고 있습니다.
말 그대로 Java와 Android 에서 100% 호환가능하며 여러 platform 에서 동작하는 언어라고 정의하고 있는데요.
Kotlin은 Anroid Studio 개발사인 JetBrain 社 에서 만든 언어로 Kotlin/JVM, Kotlin/JS, Kotlin/Native 등 여러 환경에서 동작을 합니다.
Java 와 100% 호환이 되므로 Android의 API 들을 그대로 사용할 수 있고, Ant, Maven, Gradle과 같은 빌드 시스템을 사용할 수 있어 기존의 Android 개발자들이 낯설치 않게 사용 가능할 것이라 생각됩니다.
Java 코드를 Kotlin코드로 변환하는 도구를 제공하고 있으며, Java 로 개발하는 것보다 비약적으로 코드의 양이 줄어들고 여러 개발자들의 번거로움을 덜어줄 수 있도록 NullPointerException에 대한 안정성이 증가하였습니다.
Kotlin 에 대해 기본문법에 대해 좀더 알아보겠습니다.
1. Kotlin 은 문장 끝에 세미콜론이 없다.
C, C++, Java 많은 언어들이 세미콜론으로 문장의 끝을 알리는데요. Kotlin의 문장 끝에는 세미콜론이 없습니다.
한 줄에 여러 문장을 표현할 때만 세미콜론을 이용합니다.
2. 전역함수 사용이 가능하다
함수가 반드시 클래스 내에 있지 않습니다.
3. new 키워드 삭제
4. 함수 선언은 [접근지정자][inline][final] fun 함수명(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입) :반환형의 형태로 한다.
5. val과 var
val은 읽기전용 변수(final 개념) 이며 var는 읽기&쓰기가 가능한 변수를 뜻합니다.
변수선언과 동시에 초기화를 하면 타입을 알아서 추론하기 때문에 변수의 타입이 생략 가능합니다.
아래의 3개 sample 코드를 통해 1~5번까지의 문법 설명이 가능하다.
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)
sayHello("GoodFortune")
val ck = ClassKotlin("GoodFortune"); val ck2 = ClassKotlin("GoodManner", "01055563262"); var ck3 = ClassKotlin("GoodMan", "01044778855", "ourhome") } }
KotlinTest.kt
fun sayHello(who:String){ val TAG: String = "KotlinTest" Log.d(TAG, "sayHello "+who) }
ClassKotlin.kt
class ClassKotlin(var name: String, var phone: String="", var addr: String ="") { }
6. Nullable
Kotlin 의 가장 큰 장점 중 하나라고 할 수 있습니다. Kotlin에서는 NullPointException 이 발생하지 않는다고 하니 많은 분들이 반가워 할 것 같습니다.
Kotlin 에서는 변수에 null을 저장하고 싶으면 타입명 뒤에 "?"를 붙여 null을 가질 수 있는 변수임을 알려줍니다.
Nullable은 null을 가질 수 있는 변수 타입을 말합니다. (그렇지 않은 변수는 Non-Null 이라고 합니다)
Non-Null 변수인 경우 값이 null 이 아님을 보장할 수 있으므로 Null 체크가 필요없으며 NullPointerException도 발생하지 않습니다.
Nullable 변수에 대해서는 null 체크가 없으면 컴파일러에 의해 오류가 발생합니다.
아래 sample code 에서 checkphone 은 Nullable 변수이므로 checkphone.length 를 사용시 compile error 를 발생시킵니다.
class ClassKotlin(var name: String, var phone: String="", var addr: String ="") { fun checkInformation(){ var checkname: String = name var checkphone: String? = phone if ( checkname.length > 0 ) { // OK }
if ( checkphone.length > 0) { // compile error }
} }
7. When 문
switch 문의 변형이라고도 볼 수 있는데요. switch-case 에서는 하나의 변수값에 대해 integer 형으로만 구분할 수 있는데 when 문은 아래와 같이 다양하게 사용될 수 있습니다.
when{ name.equals("GoodFortune") -> Log.d(TAG, "GoodTortune") phone.length < 9 -> Log.d(TAG, "phone number is short") }
간단한 문법에 대해서 알아보았는데, 다음번엔 Android Studio 3.0 에서 직접 사용하는 방법에 대해서도 알아보려고 합니다.
Android Studio 3.0 에서 JAVA 코드를 Kotlin으로 변환도 가능하다고 하네요^^