제네릭 제네릭 선언 제네릭 선언을 위해서는 하나 이상의 타입 파라미터를 추가해야 한다. 선언을 사용할 때는 실제 타입을 지정한다. open class P(val t: T) class Box(t: T): P(t) // 생성자 위임 호출 시 타입 인자 추론 x. 생략할 수 없음 fun main() { val box1 = Box(1) val box2 = Box(1) // 생성자 호출 시 타입 인자 생략 o } 컴파일러가 타입을 추론할 수 있으면 타입 인자 생략 가능 (자바와 달리 까지 생략) 부모 생성자를 위임 호출할 때는 타입 인자를 추론해주지 못하므로 타입 인자를 꼭 명시해야 한다. 클래스 안에서는 타입 파라미터를 프로퍼티/함수의 타입, 다른 제네릭 선언의 타입으로 사용할 수 있다. 2. 바운드 fun s..
컬렉션 엘리먼트들로 이뤄진 그룹을 저장하기 위해 설계된 객체 컬렉션을 조작하는 모든 연산이 인라인 함수 fun main() { val l1 = listOf(1, 2, 3) l1.add(4) // error val l2 = mutableListOf(1, 2, 3) l2.add(4) // ok } 자바의 컬렉션과 다르게 불변 컬렉션과 가변 컬렉션을 구분한다. (Mutable) 불변 컬렉션은 생성한 다음에 원소를 추가/삭제할 수 없다. 이터러블과 시퀀스의 차이 두 컬렉션 모두 원소를 순회하는 기능. fun main() { listOf(1,2,3) .filter { print("F$it "); it % 2 == 1 } .map { print("M$it "); it * 2} .forEach { print("E$i..
클래스 계층 상속 주생성자 뒤에 :를 넣고 상위 클래스 이름을 넣는다. 상위 클래스를 명시하지 않으면 Any를 상속하는 것으로 간주한다. open 키워드는 상속에 열려있다는 의미다. 데이터 클래스: oepn x. 다른 클래스 상속 o 인라인 클래스: open x. 다른 클래스 상속 x 객체: open x. 다른 클래스 상속 o 클래스 멤버 vs 확장 open class Parent { open fun print() { println("parent") } } fun Parent.ext() { println("parent extension") } class Child : Parent() { override fun print() { println("child") } } fun Child.ext() { prin..
클래스 종류 이넘 클래스 enum class Week { MON, TUE, WED, THU, FRI, SAT, SUN } fun Week.isWorkDay() = this != Week.SAT && this != Week.SUN fun main() { println(Week.MON.isWorkDay()) println(Week.SAT.isWorkDay()) } 미리 정의된 상수의 집합을 표현하는 클래스. (컴파일 시점 상수) 어떤 값이 가능한 범위 안에 들어가 있는지 일일이 검사할 필요가 없어 type-safe하다. 컴파일러는 이넘 타입의 변수가 이넘 클래스에 정의된 값 중 하나를 사용하는지 검사한다. 미리 정해진 전역 상수를 정의하기 때문에, 객체와 마찬가지로 내부 클래스나 함수 본문에 정의할 수 없다..
영역 함수 영역 함수를 통해 지역 변수를 명시적으로 선언하지 않고 식의 값이 들어있는 영역을 정의해서 코드를 단순화할 수 있다. 모든 영역 함수는 인라인 함수이기 때문에 런타임 부가 비용이 없다. extension run() class Foo { var a: Int = 0 var b: String = "" fun post(): String { return "a = $a, b = $b" } } fun main() { val f = Foo().run { a = 4 b = "abc" post() } println(f) } 확장 함수 형태이며, 람다의 결과를 반환한다. 일반적으로 객체 상태를 설정하고, 객체의 결과를 만들어낸다. → 지역 변수의 가시성을 세밀하게 제어할 수 있다. 2. run() class Fo..
확장 클래스 밖에서 함수나 프로퍼티를 멤버인 것처럼 쓸 수 있도록 선언할 수 있게 해주는 기능. 기존 클래스를 변경하지 않고도 기존 클래스를 확장할 수 있다. 확장 함수 fun String.truncate(maxLength: Int): String { return if (length Int): Int { var result = numbers.firstOrNull() ?: throw IllegalArgumentException("Empty array") for (i in 1..numbers.lastIndex) result = result.op(numbers[i]) return result } fun Int.max(other: Int) = if (this > other) this else other fun ..
고차 함수 함수형 언어는 함수를 first class 값으로 취급한다. 즉, 함수를 다른 일반적인 타입과 똑같이 변수에 값을 읽거나 쓸 수 있고 함수에 값을 전달하거나 함수가 값을 반환할 수 있다는 뜻이다. 고차 함수 함수를 인자로 받거나 함수를 반환하는 함수. fun aggregate(numbers: IntArray, op: (Int, Int) -> Int): Int { var result = numbers.firstOrNull() ?: throw IllegalArgumentException("Empty array") for (i in 1..numbers.lastIndex) result = op(result, numbers[i]) return result } fun main() { println(agg..
Factory Pattern 객체 생성을 처리하는 패턴. 객체를 사용하는 코드와 생성하는 코드를 분리한다. 팩토리 패턴이 필요한 경우 class Client { fun orderPizza(type: String): Pizza? { var pizza: Pizza? = null when (type) { "cheese" -> pizza = CheesePizza() "pepperoni" -> pizza = PepperoniPizza() "clam" -> pizza = ClamPizza() "veggie" -> pizza = VeggiePizza() } pizza?.prepare() pizza?.bake() pizza?.cut() pizza?.box() return pizza } } 구상 클래스를 생성하는 코드가..