Kotlin Koans Workshop - IV. properties

이미지 출처: https://kotlinlang.org/assets/images/open-graph/kotlin_250x250.png

테스트케이스로 코틀린 문법익히기

Chapter4 - Kotlin Property 이해하기

Kotlin Github repository의 kotlin-koans 프로젝트를 기반으로 포스팅 되었음을 밝힘니다.
출처: https://github.com/Kotlin/kotlin-koans

목차

custom setter 이용하기 목차 ⇈

src package

1
2
3
4
5
6
7
8
9
10
// propertyWithCounter property에 custom setter를 구현해서 호출 시 마다 counter가 1씩 증가되게 합니다.   
// property field에는 넘겨받은 값을 할당합니다.
class PropertyExample() {
var counter = 0
var propertyWithCounter: Int? = null
set(v: Int?) {
field = v
counter++
}
}

test package

1
2
3
4
5
6
7
8
9
10
// 테스트케이스가 실행되면 propertyWithCounter가 3번 호출되므로 counter는 3이되고, 마지막에 할당한 값은 32이므로 property의 field값은 32가 됩니다.   
@Test fun testPropertyWithCounter() {
val q = PropertyExample()
q.propertyWithCounter = 14
q.propertyWithCounter = 21
q.propertyWithCounter = 32
assertEquals("The property q.counter should contain the number of assignments to q.propertyWithCounter:", 3, q.counter)
// Here we have to use !! due to false smart cast impossible
assertEquals("The property q.propertyWithCounter should be set:", 32, q.propertyWithCounter!!)
}

custom getter 이용하기 목차 ⇈

src package

1
2
3
4
5
6
7
8
9
10
11
// 생성자에서 initializer에 람다식을 넘겨받도록 합니다.   
// lazyValue property의 field값이 null인 경우 initializer()를 호출하여 함수 블럭을 실행하고 Int값을 넘겨받아 field값에 할당합니다.
class LazyProperty(val initializer: () -> Int) {
private val lazyValue: Int? = null
get() {
if (field == null) field = initializer()
return field
}
val lazy: Int
get() = lazyValue!!
}

test package

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test fun testLazy() {
var initialized = false
val lazyProperty = LazyProperty({ initialized = true; 42 })
assertFalse("Property shouldn't be initialized before access", initialized)
// lazyProperty.lazy 코드가 호출되고 lazyValue field값이 null이므로 생성자에 전달한 람다식이 실행됩니다.
val result: Int = lazyProperty.lazy
assertTrue("Property should be initialized after access", initialized)
assertEquals(42, result)
}

@Test fun initializedOnce() {
var initialized = 0
val lazyProperty = LazyProperty( { initialized++; 42 })
// lazyProperty.lazy 코드가 호출되고 lazyValue field값이 null이므로 생성자에 전달한 람다식이 실행됩니다.
lazyProperty.lazy
// lazyValue field값이 null이 아니므로 생성자에 전달한 람다식이 실행되지 않습니다.
lazyProperty.lazy
assertEquals("Lazy property should be initialized once", 1, initialized)

}

lazy function으로 초기화 위임하기1 목차 ⇈

src package

1
2
3
4
// lazy function을 이용하여 이전 예제에서 사용했던 custom getter를 대체할 수 있습니다.
class LazyPropertyUsingDelegates(val initializer: () -> Int) {
val lazyValue: Int by lazy(initializer)
}

test package

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test fun testLazy() {
var initialized = false
val lazyProperty = LazyPropertyUsingDelegates({ initialized = true; 42 })
assertFalse("Property shouldn't be initialized before access", initialized)
val result: Int = lazyProperty.lazyValue
assertTrue("Property should be initialized after access", initialized)
assertEquals(42, result)
}

@Test fun initializedOnce() {
var initialized = 0
val lazyProperty = LazyPropertyUsingDelegates( { initialized++; 42 })
lazyProperty.lazyValue
lazyProperty.lazyValue
assertEquals("Lazy property should be initialized once", 1, initialized)

}

lazy function으로 초기화 위임하기2 목차 ⇈

src package

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class D {
var date by EffectiveDate()
// The property date$delegate of type EffectiveDate is created;
// the generated 'get' and 'set' accessors for 'date' are delegated to it.
// You can look at the bytecode (by calling "Show Kotlin Bytecode" action in IntelliJ IDEA) for details.
}

class EffectiveDate<R> : ReadWriteProperty<R, MyDate> {
var timeInMillis: Long? = null

operator override fun getValue(thisRef: R, property: KProperty<*>): MyDate = timeInMillis!!.toDate()
operator override fun setValue(thisRef: R, property: KProperty<*>, value: MyDate) { timeInMillis = value.toMillis() }
}

fun MyDate.toMillis(): Long {
val c = Calendar.getInstance()
c.set(year, month, dayOfMonth, 0, 0, 0)
c.set(Calendar.MILLISECOND, 0)
return c.timeInMillis
}

fun Long.toDate(): MyDate {
val c = Calendar.getInstance()
c.timeInMillis = this
return MyDate(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DATE))
}

test package

1
2
3
4
5
6
7
8
@Test fun testDate() {
val d = D()
/* Month numbering starts with 0 (0-Jan, 1-Feb, ... 11-Dec) */
d.date = MyDate(2014, 1, 13)
assertEquals(2014, d.date.year)
assertEquals(1, d.date.month)
assertEquals(13, d.date.dayOfMonth)
}

Table of contents


Open source project on GitHub


Jupyter/IPython Notebook


Open API


NoSQL


Jekyll


Gradle


Kotlin


C++

  • C++ keywords
  • 윤성우 열혈강의 C++ 프로그래밍 예제코드 [펼치기]
    1. C언어 기반의 C++ 1
      • printf와 scanf를 대신하는 입출력 방식
      • 함수 오버로딩(Function Overloading)
      • 매개변수의 디폴트 값(Default Value)
      • 인라인 함수(Inline)함수
      • 이름공간(namespace)에 대한 소개
    2. C언어 기반의 C++ 2
      • 새로운 자료형 bool
      • 참조자(Reference)의 이해
      • 참조자(Reference)와 함수
      • maloc & free를 대신하는 new & delete
      • C++에서 C언어의 표준함수 호출하기
    3. 클래스의 기본
      • C++에서의 구조체
      • 클래스(Class)와 객체(Object)
      • 객체지향 프로그래밍의 이해
    4. 클래스의 완성
      • 정보은닉(Information Hiding)
      • 캡슐화(Encapsulation)
      • 생성자(Constructor)와 소멸자(Destructor)
      • 클래스와 배열 그리고 this 포인터
    5. 복사 생성자
      • ‘복사 생성자’ 와의 첫 만남
      • ‘깊은 복사’와 ‘얕은 복사’
      • 복사 생성자의 호출시점
    6. friend와 static 그리고 const
      • const와 관련해서 아직 못다한 이야기
      • 클래스와 함수에 대한 friend 선언
      • C++에서의 static
    7. 상속(Inheritance)의 이해
      • 상속에 들어가기에 앞서
      • 상속의 문법적인 이해
      • protected 선언과 세 가지 형태의 상속
      • 상속을 위한 조건
    8. 상속과 다형성
      • 객체 포인터의 참조관계
      • 가상함수(Vitual Function)
      • 가상 소멸자와 참조자의 참조 가능성
    9. 가상(Virtual)의 원리와 다중상속
      • 멤버함수와 가상함수의 동작원리
      • 다중상속(Multiple Inheritance)에 대한 이해
    10. 연산자 오버로딩 1
      • 연산자 오버로딩의 이해와 유형
      • 단항 연산자의 오버로딩의
      • 교환법칙 문제의 해결
      • cout, cin 그리고 endl의 정체
    11. 연산자 오버로딩 2
      • 반드시 해야 하는 대입 연산자의 오버로딩
      • 배열의 인덱스 연산자 오버로딩
      • 그 이외의 연산자 오버로딩
    12. String 클래스의 디자인
      • C++ 표준과 표즌 string 클래스
      • 문자열 처리 클래스의 정의
    13. 템플릿(Template) 1
      • 템플릿(Template)에 대한 이해와 함수 템플릿
      • 클래스 템플릿(Class Temlpate)
    14. 템플릿(Template) 2
      • Chapter 13에서 공부한 내용의 확장
      • 클래스 템플릿의 특수화(Class Temlpate Specialization)
      • 템플릿의 인자
      • 템플릿과 static
    15. 예외처리(Exception Handling)
      • 예외상황과 예외처리의 이해
      • C++의 예외처리 메커니즘
      • Stack Unwinding(스택 풀기)
      • 예외상황을 표현하는 예외 클래스의 설계
      • 예외처리와 관련된 또 다른 특성들
    16. C++의 형 변환 연산자
      • C++에서의 형 변환 연산

ETC