/* 조건에 따른 변수값 지정 */ funmain() { var result = doWhen(3.toLong()) println(result) }
fundoWhen(a: Any):Any { // Any: 어떤 자료형이든 상관없이 호환되는 코틀린 최상위 자료형 var result = when(a) { 1 -> "숫자 1입니다" "Kotlin" -> "문자열 Kotlin입니다. Hello, Kotlin" isLong -> "Long 타입입니다" !is String -> "String 타입이 아닙니다" else -> "어떤 조건도 맞지 않습니다" } return result }
반복문
파이썬과 다르게 마지막 값까지 포함하여 반복
1 2 3 4 5
funmain() { for (i in0..9) { println(i) } }
1씩 증가하는 것이 아닌 단계별 증가를 시키기 위해서는 step을 사용하면 된다
1 2 3 4 5
funmain() { for (i in0..9 step 3) { println(i) } }
..이 아닌 downTo를 이용하여 감소를 시킬 수 있다
1 2 3 4 5
funmain() { for (i in9 downTo 0) { println(i) } }
1 2 3 4 5
funmain() { for (i in'a'..'e') { println(i) } }
step을 사용할 수도 있다
character형태가 숫자로도 나타낼 수 있기에…
흐름제어
break문과 continue문은 동일하나 코틀린에서 label 기능을 사용 할 수 있다
다중 반복문을 통해서 label의 기능을 살펴보자
먼저, 일반적인 이중 반복문에서 break를 이용한 방식을 보면 첫번째 for문으로 인해 이후의 값들도 지속됨을 알 수 있다
1 2 3 4 5 6 7 8 9 10 11 12
funmain() { for (i in1..10) { for (j in1..10) { print(i) print("\t") println(j) if (i == 1 && j == 2) { break } } } }
다음의 label의 기능을 쓴 방식은 처음 for문을 빠져나가게 해줌으로서 이후의 값이 출력되지 않는다
1 2 3 4 5 6 7 8 9 10 11 12
funmain() { loop@for (i in1..10) { for (j in1..10) { print(i) print("\t") println(j) if (i == 1 && j == 2) { break@loop } } } }
이렇게 보았을 때 시간 복잡도상으로 따진다면 큰 이득을 얻을 수 있다
보통은 함수처리하여 return으로 마무리 했었는데 좋은 기능이 추가 되었음을 알 수 있다
Class
고유의 특징값(속성) + 기능의 구현(함수)로 이루어짐
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
funmain() { var a = Person("오세훈", 1961) var b = Person("박영선", 1960) var c = Person("안철수", 1962) a.introduce() b.introduce() c.introduce() }
classPerson(var name:String, val birthYear: Int) { funintroduce() { println("안녕하십니까 시민 여러분 저는 ${birthYear}년생 ${name} 입니다") } }
여기서 클래스 옆에 var name:String, val birthYear: Int는 클래스의 속성들을 선언함과 동시에 생성자 역시 선언하는 방법
생성자(Constructor)
새로운 인스턴스를 만들기 위해 호출하는 특수한 함수
생성자를 호출하면 클래스의 인스턴스를 만들어 반환 받을 수 있음
인스턴스의 속성을 초기화
인스턴스 생성시 구문을 수행
init함수를 통해 구문 수행 가능
init 함수는 파라미터나 반환형이 없는 특수한 함수로 생성자가 생성될 때 실행됨
1 2 3 4 5 6 7 8 9 10 11
funmain() { var a = Person("오세훈", 1961) var b = Person("박영선", 1960) var c = Person("안철수", 1962) }
classPerson(var name:String, val birthYear: Int) { init { println("안녕하십니까 시민 여러분 저는 ${this.birthYear}년생 ${this.name} 입니다") } }
기본 생성자: 클래스를 만들 때 기본으로 선언init
보조 생성자: 필요에 따라 추가적으로 선언constructor
:man_teacher:보조 생성자를 만들 때는 반드시 기본 생성자를 통해 속성을 초기화 해주어야 한다
보조 생성자가 기본 생성자를 호출하도록 하려면 아래와 같이 :this라는 키워드를 사용하고 기본 파라미터가 필요한 부분을 괄호 안에 넣어주면 된다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
funmain() { var a = Person("오세훈", 1961) var b = Person("박영선", 1960) var c = Person("안철수", 1962) var baby1 = Person("신생아1") var baby2 = Person("신생아2") }
classPerson(var name:String, val birthYear: Int) { init { println("안녕하십니까 시민 여러분 저는 ${ this.birthYear }년생 ${ this.name } 입니다") } constructor(name:String):this(name, 2021) { println("보조 생성자가 실행되었습니다") println("생성된 보조 생성자 ${ name }입니다") } }
funmain() { var a = Animal("John", 3, "DOG") var b = Dog("John", 3) a.introduce() b.introduce() // a.bark() // 부모클래스에서 자식클래스 함수 접근X b.bark() var c = Cat("Loi", 2) c.introduce() c.meow() }
openclassAnimal(var name:String, var age:Int, var type:String) { funintroduce() { println("${type}${name}${age}") } }
classDog(name:String, age:Int) : Animal (name, age, "DOG") { // 클래스의 자체 속성으로 만들어주는 var을 붙이지 말것 // 같은 속성을 붙이게 되면 서브 클래스의 속성이 되기에 상속 규칙 무시됨 funbark() { println("Bark! Bark!") } }
funmain() { val calculate:(Int, Int) -> Int = { a, b -> println(a) println(b) a + b // return값, return 타입 있을시에는 맨 아래줄 리턴 대상 } println(calculate(3, 5)) }
파라미터가 없을 시,
1 2 3 4 5 6
funmain() { val calculate:() -> Unit = { println("계산값 없음") } calculate() }
파라미터가 하나일 경우 다른방법으로 파라미터 가져오기: it
1 2 3 4 5 6
funmain() { val calculate:(Int) -> Unit = { println("${it} 파라미터 하나 가져오기") } calculate(7) }
Scope Function
함수형 언어의 특징을 조금 더 편리하게 사용할 수 있도록 기본 제공하는 함수들
apply
run
with
also
let
apply: 인스턴스를 생성한 후 변수에 담기 전에 ‘초기화 과정’을 수행할 때 많이 사용됨
1 2 3 4 5 6 7 8 9 10 11 12 13
funmain() { var book = Book("Kotlin", 30000).apply { name = "[Sale]" + name discount() } println(book.price) }