고차 함수 함수형 언어는 함수를 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..
![](http://i1.daumcdn.net/thumb/C148x148.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/o9N5i/btsmyumj74U/87jFFjbBh484Lk0C39iQNk/img.png)
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 } } 구상 클래스를 생성하는 코드가..
![](http://i1.daumcdn.net/thumb/C148x148.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/em0PuR/btsmyYU2BFw/FfgE7ZWiHkLXqnQxOx08bk/img.jpg)
Singleton Pattern 클래스 인스턴스를 하나만 만드는 패턴 생성자를 private으로 두고, 하나뿐인 인스턴스의 전역 접근을 제공한다. 인스턴스가 필요할 때 클래스에 요청하고, 요청이 들어오면 하나뿐인 인스턴스를 반환한다. → lazy instantiation 싱글톤 패턴이 필요한 경우 인스턴스가 하나만 존재해야 하는 경우 사용한다. (스레드 풀, 캐시, 로그 등) 이런 경우 인스턴스가 여러개라면, 자원을 불필요하게 사용하거나 결과가 일관되지 않을 수 있다. 전역 변수를 사용해서 인스턴스를 생성하면, 필요하지 않은 경우에도 인스턴스가 생성되어 자원을 잡아먹을 수 있다. 여러 곳에서 같은 데이터를 공유할 수 있다. 구조 구현 방식 1) 기존 싱글톤 패턴 방식 public class Singlet..
![](http://i1.daumcdn.net/thumb/C148x148.fwebp.q85/?fname=https://blog.kakaocdn.net/dn/PxZ0v/btsmwXolgIo/oaof5sJ5bU0P4zzRCzLEQk/img.png)
Observer Pattern 어떤 객체의 상태가 바뀌면 그 객체를 구독하는 다른 객체(옵저버)에게 알림을 보내는 패턴 Subject Observer에게 데이터가 변경될 때마다 알려주는 역할 새로운 값을 Observer에게 전달한다. 옵저버 패턴의 대상이 되는 데이터를 관리한다. Observer Subject를 구독하고, Subject의 데이터가 바뀌면 그 데이터를 전달받는다. 특징 일대다 의존성 하나의 Subject에 여러 Observer가 연관된다. Observer는 데이터를 가질 필요가 없고, Subject가 알림을 보내길 기다린다. → Subject에 의존 여러 객체가 동일한 데이터를 관리하지 않고, 하나의 객체(Subject)만 가지고 있기 때문에 깔끔한 코드. 느슨한 결합 (Loose Coup..
객체 선언 object Application { val name = "My Application" override fun toString() = name } fun describe(app: Application) = app.name // Application을 타입으로 사용 fun main() { println(describe(Application)) // Application을 값으로 사용 println(Application) } 객체를 통해 클래스의 인스턴스가 하나만 존재하는 싱글톤 패턴을 사용할 수 있다. object 키워드를 사용하여 선언한다. 객체의 인스턴스가 하나뿐이므로 객체를 타입으로도 사용할 수 있다. 실제 객체 인스턴스에 접근할 때까지 초기화가 지연된다. 생성자가 존재하지 않는다. (암시..
늦은 초기화 (lateinit) 인스턴스를 생성할 때 프로퍼티를 초기화하지 않고, 필요시 초기화하기 위해 사용한다. 값을 읽을 때 프로퍼티가 초기화되지 않으면 UninitializedPropertyAccessException 예외를 던진다. lateinit 프로퍼티의 조건 가변 프로퍼티로 정의해야 한다. 참조 타입, non-nullable type이어야 한다. (내부에서는 초기화되지 않은 상태를 표현하기 위해 널을 사용하기 때문) 선언과 동시에 초기화할 수 없다. 최상위 프로퍼티와 지역 변수에서도 사용할 수 있다. 2. 커스텀 접근자 프로퍼티는 커스텀 접근자를 통해 변수와 함수의 동작을 하나의 선언에 조합할 수 있다. 커스텀 접근자는 프로퍼티 값을 읽거나 쓸 때 호출되는 함수다. 커스텀 게터 class ..
널이 될 수 있는 타입과 널이 될 수 없는 타입을 구분한다. → 널 발생 여부를 컴파일 시점으로 옮겨주기 때문에 NullPointerException 예외를 방지할 수 있다. 기본적으로 코틀린의 모든 타입은 널이 될 수 없는 타입이다. → 널에 대한 검사를 추가로 수행할 필요가 없다. 널이 될 수 있는 타입(nullable type) 타입 뒤에 ?를 붙여 지정할 수 있다. ex) val s: String? = "abc" 널이 될 수 없는 타입(non-nullable type)의 상위 타입이므로, nullable type에 non-nullable type의 값을 대입할 수 있다. fun isLetterString(s: String?): Boolean { if(s.isEmpty()) return false ..
클래스 구조 class Person { var firstName: String = "" var familyName: String = "" var age: Int = 0 fun fullName() = "$firstName $familyName" fun showMe() { println("${fullName()}: $age") } } 위 클래스의 인스턴스마다 firstName, familyName. age라는 프로퍼티와 fullName(), showMe()라는 함수가 포함된다. cf) 파일명을 public 클래스의 이름과 동일하게 만들지 않아도 된다. 한 파일에 여러 public 클래스가 존재할 수 있다. 2. 생성자 주생성자 class Person(firstName: String, familyName: S..