본문으로 바로가기

기본 변수 null 허용하지 않음. null pointer exception(NPE) 차단을 위함.

단, nullable 변수 선언해서 사용은 가능함.

fun main() {
  var variable: Int = 1
  var nullable: Int? = null // nullable. 주의해서 사용할 것
  val contants: Int = 2
    
  println(variable)
  println(nullable)
  println(contants)
}

 

정수 타입

독특하게도 8진수는 지원하지 않는다. 오로지 2진수, 10진수, 16진수.

fun main() {
  var intValue:Int = 1234 // 4byte 10진수
  var longValue: Long = 1234L // 8byte 10진수
  var hexValue: Int = 0x1af // 16진수 접두사 0x
  var binValue: Int = 0b11000101 // 2진수 접두사 0b
}

 

실수 타입. 유효 자리 수에 유의

fun main() {
  var floatValue: Float = 12.4f // 4byte. 유효 7자리 수
  var doubleValue: Double = 12.4 // 8byte. 유효 16자리 수
  var doubleWithExp: Double = 12.4e5 // 8byte. 유효 16자리 수
}

 

문자형, 불린형

fun main() {
  var charValue: Char = 'A' // 홑따옴표로 감쌀 것
  var stringValue: String = "abcdefg" // 문자열은 겹따옴표
    
  var trueValue: Boolean = true
}

 

명시적 형변환만 가능하며 암시적 형변환 불가능

fun main() {
  var a:Int = 1263
  var b:Long = a.toLong() // 이렇듯 명시적 형변환만 가능하며 암시적 형변환은 지원하지 않음.
  
  println(b)
}

 

배열

fun main() {
  var intArr = arrayOf(1, 2, 3)
  var nullArr = arrayOfNulls<Int>(3) // 크기 3인 null로 채워진 배열
  
  println(intArr[0]) // 1
  
  intArr[2] = 1000
  println(intArr[2]) // 1000
}

 

type infer

typescript에서의 타입 추론이 여기에서도 된다. 선언시에 초기화만 한다면 자료형이 추론된다.

fun main() {
   var a = 123 // Int
   var b = 12L // Long
   var c = 1.2 // double
   var d = 1.3f // float
   var e = '3' // char
   var f = "wowowo" // String
   var g = arrayOf(1, 2) // Array<Int>, ArrayInt
}

 

함수.

독특하게 js의 arrow function과 비슷한 single expression function 존재

fun main() {
   println(add(1, 2))
   println(singleExpAdd(1, 2))
}

fun add(a: Int, b: Int):Int {
    return a + b
}

// single expression function
// return값 type infer됨
fun singleExpAdd(a:Int, b:Int) = a + b

 

 

자료형 체크를 위한 is와 !is가 존재한다.

fun main() {
   var a = 3
    
   if (a is Int) {
       println("a is int type")
   } else {
       println("a is not int type")
   }
}

 

switch가 없고 when문이 있다. 

참고로 when에서 만족하는 첫번째 조건에서 return된다. 

fun main() {
   doWhen(2) // 이거 정수형이야
   doWhen(1.2) // 어디에도 걸리지 않았습니다
}

fun doWhen(a: Any) {
    when(a) {
        1 -> println("이거 1이야")
        "Darren" -> println("다롄")
        is Int -> println("이거 정수형이야")
        !is Double -> println("이거 더블형 아니야")
        else -> println("어디에도 걸리지 않았습니다")
    }
}

 

for문

특이한 표기법을 가지고 있다. .. 으로 범위를 표현하고 step으로 뗀다.

fun main() {
    for (i in 0..5 step 2) {
        print(i)
    }
}

감소하는 케이스는 ..가 아니라 downTo를 붙여야 한다.

fun main() {
    for (i in 9 downTo 2 step 2) {
        print(i)
    }
}

문자도 가능하다.

fun main() {
    for (i in 'a'..'e') {
        print(i)
    }
}

 

Label 표현식

break, continue에서 Label 표현식을 통해서 특정 loop를 탈출할 수 있다.  

 

아래 코드는 내부에서 break하더라도 myLoop로 지정한 외곽의 반복문까지 탈출하게 된다.

fun main() {
    myLoop@for (i in 1..10) {
        for (j in 1..10) {
            if (i == 1 && j == 1) break@myLoop
            print("$i, $j") // print 되면 앙돼요
        }
    }
}

 

 

class

 

기본 생성자만 활용한 class

fun main() {
    // new 할당자가 없다! 그냥 쓰면 된다.
    var darren = Person("darren", 27)
}


// method 없는 클래스는 아래와 같이 간단히 선언 가능, age에 기본값으로 100 할당.
class Person(var name: String, val age: Int = 100)

 

메서드 선언

// method를 선언하려면 아래와 같이 단순히 함수를 내부에서 선언하기만 하면 됨
class Person(var name: String, val age: Int) {
    fun greeting() {
        println("hello my name is $name and $age years old")
    }
}

 

초기화 영역. 인스턴스가 생성될 때 트리거 된다.

class Person (var name:String, var age: Int) {
    // 초기화 영역 -> init: 인스턴스가 생성될 때 호출되는 함수
    init {
        println("${this.name}, ${this.age}")
    }
}

 

보조 생성자인 constructor를 통해서 생성할 수 있음. 사용시 무조건 this로 바인딩해줘야 함.

class Person (var name:String, var age: Int) {
    // 초기화 영역은 보조 생성자인 constructor보다 먼저 실행됨
    init {
        println("${this.name}, ${this.age}")
    }

    // 보조 생성자. 사용할 때 반드시 기본 생성자를 통해 속성을 초기화해주어야 함.
    // this(...) 꼴로 초기화할 수 있으며, 여기서 기본값을 할당할 수도 있음.
    constructor(name: String): this(name, 33) {
        println("보조 생성자 실행")
    }
}

 

상속

 

 코틀린은 상속 금지가 기본값이다. 상속하려면 open을 앞에 붙여줘야만 해당 클래스를 부모 클래스로 사용할 수 있다.

fun main() {
    var happy = Dog("happy", 6)

    happy.bark()
    happy.introduce()
}

// open -> 이 클래스는 부모 클래스가 될 수 있다.
open class Animal(var name: String, var age: Int, var type: String) {
    fun introduce() {
        println("저는 ${type} ${name}이고 ${age}살 입니다")
    }
}

// 부모 클래스에 존재하는 속성과 같은 이름의 속성을 가질 수 없음 -> 같은 속성 선언 금지. (var)
class Dog(name: String, age:Int): Animal(name, age, "dog") {
    fun bark() {
        println("bowwow")
    }
}

 

overriding

부모 클래스와 같은 이름과 형태를 가진 함수를 서브 클래스에서 구현할 수 없다.

아래 예시를 보자.

fun main() {
    var a = Warm()
    a.eat() // Kotlin: 'eat' hides member of supertype 'Animal' and needs 'override' modifier
}

open class Animal {
    fun eat() {
        println("eat food, bro")
    }
}

class Warm: Animal() {
    fun eat() {
        println("eat rotten food, bro")
    }
}

 

아래와 같이 부모 메서드에는 open 키워드, 자식 메서드에는 override 키워드를 달아주면 오버라이딩이 가능해서 에러가 나지 않는다.

fun main() {
    var a = Warm()
    a.eat() // eat rotten food, bro
}

open class Animal {
    open fun eat() {
        println("eat food, bro")
    }
}

class Warm: Animal() {
    override fun eat() {
        println("eat rotten food, bro")
    }
}

 

추상화 1: abstract class

open대신 abstract 키워드를 써주면 된다.

abstract 메서드는 body가 없어야 한다.

fun main() {
    var venom = Venom()
    venom.eat()
}

abstract class Animal {
    // A function 'eat' with body cannot be abstract 즉, fun에 body가 없어야 함
    abstract fun eat()
}

class Venom: Animal() {
    override fun eat() {
        println("yummy")
    }
}

 

추상화 2: 인터페이스

코틀린에서의 인터페이스는 타 언어와는 조금 다른 점이 있다. 코틀린의 인터페이스는 추상함수 뿐만 아니라 일반함수까지도 가질 수 있다 

  • 포함된 모든 함수를 자식 클래스에서 구현, 재정의가 가능하다.
  • open, abstract 키워드가 별도로 필요 없다.
    • 인터페이스에서 구현부가 있는 함수 -> open 함수
    • 인터페이스에서 구현부가 없는 함수 -> abstract 함수
fun main() {
    var dog = Dog()
    dog.eat()
    dog.run()
}

interface Runner {
    // 구현부 없으므로 abstract 취급
    fun run()
}

interface Eater {
    // 구현부 있으므로 open 취급
    fun eat() {
        print("eat")
    }
}

class Dog: Runner, Eater {
    // 추상 함수의 구체화
    override fun run() {
        println("run")
    }

    // 일반 함수 override
    override fun eat() {
        println("eat eat")
    }
}

 

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체