1. 함수
리턴타입이 없는 경우 즉, 자바에서의 void가 코틀린에서는 Unit 이다. 또한 이는 생략이 가능하다.
package com.example.kotlin
fun main () {
val result = test2(1,2)
val result2 = test3(1,c=5) // 매개 변수를 전부 입력하지않고 지정해줄 수 있다.
println(result2)
}
//2.함수
fun test() : Unit { // Unit이 생략되어있는데 이 친구는 void 와 동일화다
println("test")
}
fun test1() : Int {
return 1
}
fun test2(a: Int, b: Int) : Int { // 매개변수는 변수가 나오고 자료형이 나온다
println(a+b)
return a+b
}
// 코틀린에서는 오버로딩이 필요없다 이렇게 디폴트 값 선언할 수 있다. 이렇게 코드를 줄여 간결성있는 코드를 작성가능함
fun test3(a: Int, b: Int = 3, c: Int = 4) : Int { // 매개변수는 변수가 나오고 자료형이 나온다
println(a+c)
return a+b
}
fun times(a: Int, b:Int) : Int{
return a+b
}
fun times2(a: Int, b:Int) = a+b // 위와 아래는 동일하다 single expression
// trailing comma
2. 변수
- val = value (값) : 변경이 불가능하다
- var = variable (변경가능한) : 변경이 가능하다
- val 인지 var 인지 먼저 알려준 후 변수명, 타입, 값 순으로 작성하면 된다
- 코틀린의 타입 추론 기능 때문에 val 의 경우엔 타입을 작성해주지 않아도 컴파일 오류가 나지 않는다.
fun main() {
val a : Int = 3
var b : Int = 4
a = 20 // 오류 발생 ( val은 값을 변경불가)
val name = "죵" // 타입 추론 기능 때문에 타입 생략이 가능하다.
}
3. 클래스
- 코틀린에서는 클래스 생성자 & 속성의 값 할당을 동시에 할 수 있다.
- default value 를 넣을 수 있다.
- 초기화 방식은 주 생성자 뿐만 아니라 init 블럭 , 부 생성자를 이용할 수 있다.
- 호출 순서는 init 블럭 이후에 부 생성자가 호출된다.
fun main() {
val user = User("죵",10)
//name을 private 이라 지정했기에 user.name 이런식의 접근은 불가능하다.
val users = Users("죵") // 아래의 Users 클래스에서 age 는 값을 지정해줬기에 이름만 작성해도 오류 X
}
class User(private val name : String, var age: Int) // 구현부가 없는 경우엔 한줄로
// 작성이 가능하기 때문에 생성자의 역할도 가능해진다
class Users(val name : String, var age: Int = 3) // 함수에서와 동일하게 값을 지정해줄수도 있다. default value
- 기본적으로 코틀린에서는 상속을 권장하지 않는다. 클래스를 상속할 수 있게 하려면 클래스 앞에 open을 작성해줘야한다.
- 생성자가 다른 방식으로 생성될 수 있다. 즉, 주 생성자 이외에 부 생성자를 만들 수 있다.
open class User(open val name: String, open var age: Int)
class Kid(override val name: String, override var age: Int) : User(name, age)
// 아이들은 user를 상속받을 수 있다.
// 현재 사용하고 있는건 주 생성자
// 주 생성자란 아래처럼 클래스명 뒤에 constructor 가 생략이 되어있는 것
class Kid constructor(override val name: String, override var age: Int) : User(name, age)
class Kid (override val name: String, override var age: Int) : User(name, age){
init { // 클래스 내에서 가장 먼저 호출되는 녀석
println("초기화 중 입니다.")
}
// secondary constructor 부 생성자
var gender: String = "female"
constructor(name: String, age: Int, gender: String) : this(name, age){
this.gender = gender
}
}
4. Null
- 코틀린에서는 자바와는 다르게 랭귀지 레벨에서 Null에서 안정성을 가져갈 수 있다.
- 기본 변수 타입에는 null 값을 부여할 수 없다.
- 타입 뒤에 ?를 붙이면 null이 가능하다. Null 허용
- !! 는 해당 변수가 현재 널 값이 아니라고 컴파일러에게 알려줘서 컴파일 에러가 나지 않도록 할 때 사용한다.
- 컴파일 단계에서 에러가 난다.
- 또한 흔히 null safe 하게 코딩하기 위해서 조건문을 통해 확인해준다. 하지만 코틀린에서는 elvis operation을 사용해 ?:의 왼쪽 객체가 non null이면 그 객체의 값이 리턴되고, null이라면 ?:의 오른쪽 값을 리턴한다.
- 변수 자체는 nullable 한 타입이지만 반드시 nullable 하지 않을 수 있다. 이 경우엔 val size = nickname!!.length 와 같이 !!를 사용해줘야한다. 하지만 되도록 쓰지 않고 타입을 선언 시 신경써주는 것이 좋다.
fun main() {
var name: String = "상아"
name = null // 빨간줄
var nickname: String? = null //타입 뒤에 ?를 붙이면 null이 가능하다.
val nickname = if(nickname == null){ //nullsafe 하게 코딩하기 위해 이렇게 작성했던게 대부분이였다.
"값이 없음"
}else {
nickname
}
nickname = "안녕"
val result = nickname?: "값이 없음" // elvis operation 만약 널이면 오른쪽 값을 내뱉어라
val size = nickname?.length
//이렇게 하게되면 만약 nickname이 null인 경우엔 더 이상 진행하지 않고 null을 내뱉어
//만약 null 이 아니면 길이를 내뱉어
}
5. String template
- 로그찍을 때 유용하다.
- 자바에서는 String 이 아닌경우 toString()을 사용해서 변환해서 보여줬다. 하지만 코틀린에서는 " " 내에 $변수명을 작성해주면 String 형으로 변환되어 보여준다.
- 또한 변수에 해당하는 메서드도 사용이 가능하다. { } (bracket) 내에 변수.메서드명 작성
fun main() {
val a = 10
val name = "안녕"
val isHigh = true
println(a.toString() + name + isHigh.toString()) // 자바의 경우
println("$a $name $isHigh") // 코틀린
// 10 안녕 true 결과값이 이렇게 나오게 된다.
println("$a ${name.length} $isHigh") // 코틀린
// 10 2 true 결과값이 이렇게 나오게 된다.
}
6. 조건식
- if-else 와 when이 있다.
- 자바에서의 조건문은 state 라면 코틀린에서는 expression 임. 즉, 값으로 사용할 수 있다.
- 삼항연산자는 없다. 대신 아래와 같이 간단하게 표현은 가능하다.
- when 절에서는 다양한 타입의 데이터를 비교할 수 있다. ex) 범위 혹은 list 등
더보기
val number : Int = if (a>20) 10 else 20
fun main(){
val a = 0
if(a>3){
println("3보다 작습니다")
}
}
fun main(){
val a = 0
val i = if(조건){
// 내용 1
}else if (조건 2){
// 조건 2
}else{
// 이외의 내용
}
} // 이런식으로 값으로 사용할 수 있다는 뜻임
fun main(){
when (a) {
case1 -> 동작1
case2 -> 동작2
else -> 동작3
}
}
fun main(){
when (a) {
case1,
case2 -> 동작2
else -> 동작3
}
} // 만약 같은 동작을 수행하는 경우엔 아래처럼 묶어줄 수 있다.
fun main() {
val x = 5
when (x) {
in 1..10 -> println("x는 1~10 사이에 있는 수")
in listOf(1,2,3,4) -> println("list안에 있는 수")
else -> println("x는 다른 수")
}
} // 다양한 타입의 데이터를 비교할 수 있다.
7. 반복문
- for 문, while 문, do-while 문 등이 있다.
- downTo는 어디까지 감소시킬지 범위를 지정하는 것이다.
fun main(){
for(i in 범위) // ex) 1..10 는 1이상 10이하를 말한다{
//반복내용 작성
}
}
fun main(){
val arr = arrayOf(1,2,3,4,5) //arrayOf는 배열을 생성하는 함수
for(i in arr){
print(i) // 이렇게 하면 배열요소 전부 나온다
}
}
fun main(){
for(i in 범위 step(증가하는 크기)) {
print(~~) //만약 범위가 0..10 이고 step이 2면 0,2,4,6,8,10 이런식으로 출력
}
}
fun main(){
for(i in 10 downTo 0 step 2){
println(i)
}
} // 변수의 값을 갑소시키고 싶은 경우 ! downTo는 for문에서 변수를 감소시키는 범위를 지정하는 것이고 변수의 값을
어디까지 감소시킬지 지정하는 것이다. 위의 예제는 10부터 0까지의 범위를 지정하고 step을 써서 2씩 감소하라고 한 것이다.
fun main() {
var i = 0
while (i < 5) {
println(i)
i++
}
}
8. 컬렉션
- 값이 변경가능한 mutable 과 변경불가능한 것으로 나뉜다.
- list, set, map 등이 있다.
9. 타입체크와 캐스팅
- is, as 를 사용한다.
fun main(){
val data: Any = "Hello, World!"
when (data) {
is String -> println("string 입니다")
is Int -> println("int 입니다")
else -> println("다른 타입 입니다")
}
}
fun cast(a : Any) {
val result = (a as? String) ?: "실패" //as를 통해서 캐스팅할 수 있고 ?를 붙이면 캐스팅이 안되는 exception 상황에서 null을 내뱉는다.
}
fun smartcast(a: Any): Int {
return if(a is String){
a.length //스마트캐스팅 즉, 캐스팅 후에 해당 변수타입과 동일하게 바로 사용가능하다.
}
}