devlog of ShinJe Kim

[TIL] 2019-08-23 (금)

|

Today I Learned

  • 자바에서의 상속은 수직 확장, 코틀린에서의 확장 함수는 수평 확장
  • 상속에서의 가장 큰 문제점 중 하나는, 상속 받은 곳에서 기존의 멤버를 수정했을 때 다른 코드들도 다 영향을 받을 수밖에 없다는 것이다. 그래서 이전에 작성한 코드들이 제대로 동작하는지를 테스트해야하는데 이러한 개념을 회귀라고 한다. 이를 위해 하는 것이 단위테스트이다. (사실 기존의 상속 개념도 제대로 안다고 할 수 없기 때문에 자바의 상속과 코틀린의 확장 함수가 어떻게 다르고, 확장 함수가 어떤 이점이 있는지 따로 정리해보자.)
  • 프레임워크와 라이브러리의 차이점. 프레임워크는 ‘룰’이 있고 ‘흐름’이 있다. 그래서 프레임워크를 도입하면 그 룰에 맞춰서 프로그램을 만들어야 한다. 하지만 라이브러리는 기존의 흐름 위에 적용할 수 있다. 프레임워크와 비슷하게 간주되는 것이 Engine(라이브러리의 집합)인데, 이것은 프레임워크와는 다른 개념이다.
  • 안드로이드 리소스 string.xml에서 따옴표나 어퍼스트로피를 쓸 때에는 꼭 이스케이프문자(\)를 써 주어야 빌드 에러가 안난다.

[TIL] 2019-08-22 (목)

|

Today I Learned

Kotlin in Action 3장

3.1 코틀린에서 컬렉션 만들기

  • 코틀린은 자바와의 호환성을 위해 자체 컬렉션 기능을 제공하지 않고 기존의 자바 컬렉션을 활용한다. 또한 자바에서 쓸 수 있는 기능보다 더 많은 기능을 제공한다.

3.2 함수를 호출하기 쉽게 만들기

  • 코틀린으로 작성한 함수를 호출할 때는 함수에 전달하는 인자 중 일부 혹은 전부의 이름을 명시할 수 있다. 이 때 혼동되는 상황을 방지하기 위해 인자 이름을 하나라도 명시했다면, 다른 인자들의 이름도 꼭 명시해야 한다.
// 기존의 자바 스타일
joinToString(Collection, " ", " ", ".")
// 코틀린
joinToString(collection, separator = " ", prefix = " ", postfix = ".")

3.2.2 디폴트 파라미터 값

코틀린에서는 아래와 같이 디폴트 파라미터 값을 지정할 수 있다. 디폴트 값을 지정하면 함수를 호출할 때 일부를 생략하여 사용할 수도 있다.

fun <T> joinToString(
    collection: Collection<T>,
    separator: String = ", ",
    prefix: String = "",
    postfix: String = ""
): String

3.2.3 정적인 유틸리티 클래스 없애기: 최상위 함수와 프로퍼티

자바에서는 클래스 안에서만 함수 정의가 가능했다. 하지만 코틀린에서는 함수를 최상위에 정의할 수 있다. 이는 JVM이 코틀린을 컴파일 할 때 함수에 대응하는 클래스가 없다면 새로운 클래스를 정의해주기 때문이다. 이 때 코틀린 컴파일러가 생성하는 클래스의 이름은 최상위 함수가 들어있는 코틀린 소스 파일의 이름과 같다. 만약 이 클래스의 이름을 변경하고 싶다면 파일 최상단에 file@JvmName("원하는 클래스 이름") 를 추가하면 된다

3.3 메소드를 다른 클래스에 추가: 확장 함수와 확장 프로퍼티

확장 함수(extension function)란 클래스의 멤버 메소드처럼 호출할 수 있지만 클래스 밖에서 정의된 함수를 의미한다. 기존의 자바 코드를 유지하면서 코틀린을 사용할 수 있도록 해주는 기능이다. 확장 함수를 가져다 쓰는 것을 ‘수신’이라고 표현한다. 확장 함수를 수신하더라도 캡슐화는 유지되어서 접근지정자가 private이나 protected인 멤버는 사용할 수 없다. 수신하는 방법은 아래와 같다.

fun String.lastChar(): Char = this.get(this.length-1)

위의 코드를 찬찬히 살펴보면, String: 수신 객체 타입(receiver type)을 의미한다. 확장 함수가 정의될 타임이다. lastChar(): 확장 함수이다. this: 수신 객체(receiver object) 이다. 수신되는 클래스의 인스턴스 객체를 의미한다.

이렇게 수신하고 나면 다른 함수와 동일한 방법으로 사용할 수 있다.

3.3.1 임포트와 확장 함수 확장 함수를 쓸 때에는 같은 이름의 다른 함수와의 충돌을 방지하기 위해 다른 함수처럼 import를 해야 한다. 임포트 방식은 기존의 클래스 임포트 방식과 동일하며, as를 사용하면 원하는 이름으로 함수를 임포트할 수 있다.

// 아래의 방식 모두 사용 가능하다.
1. import strings.lastChar
2. import strings.*
3. import strings.lastChar as last

[TIL] 2019-08-19 (월)

|

Today I Learned

  • enum 클래스 안에 메소드를 정의하는 경우에는 반드시 enum 상수 목록과 메소드 정의 사이에 세미콜론을 넣어야 한다. 코틀린에서 유일하게 세미콜론(;)이 필수인 부분이다.

[TIL] 2019-08-16 (금)

|

Today I Learned

  • ConstraintLayout 안에서는 match_parent를 되도록이면 쓰지 않아야 한다.
  • 코드의 일부분이 변경되었을 때 다른 부분을 수정하지 않아도 되도록 코드를 짜야 한다. 예를 들면 안드로이드의 ConstraintLayout 안에서 제약을 걸 때, 수직으로 나란히 놓인 1,2,3번 위젯이 있다고 치자. 이 위젯들의 start와 end를 모두 parent에 걸어도 상관은 없다. 하지만 위젯의 width가 변경되거나, 포지션이 변경될 때 모든 위젯의 코드를 수정해주어야 한다. 이를 방지하려면 1번 위젯만 parent에 제약을 걸고 나머지 2,3번 위젯의 start와 end는 1번 위젯의 start와 end에 걸면 된다. 그럼 나중에 레이아웃을 변경하고 싶을 때 1번 위젯의 너비/위치만 변경해주면 2,3번 위젯의 너비/위치는 자동으로 변경된다.
  • mediator 디자인 패턴: 복잡한 관계 속에서 모두가 1:1 관계를 가질 수 있도록, 중재자를 중간에 두는 것.
  • 의존성이 낮고, 일관적인 코드를 짜는 것이 중요하다.

[TIL] 2019-08-14 (수)

|

Today I Learned

  • android:clickable 속성을 사용할 때에는 android:focusable 속성을 같이 사용해야만 한다. clickable 속성만 추가하면 'clickable' attribute found, please also add 'focusable'...이라는 메시지가 뜬다. 메시지를 클릭해보면 아래와 같은 설명이 있다.
Inspection info:A widget that is declared to be clickable but not declared to be focusable is not accessible via the keyboard. Please add the focusable attribute as well.  
Issue id: KeyboardInaccessibleWidget

즉, 클릭이 가능하게 만들고서 focus가 안되게 하면 키보드로는 접근할수가 없다는 것이다.

  • focus가 가능하게 하려면 뷰에 android:clickable="true", android:focusable="true", android:focusableInTouchMode="true" 이 세가지 속성을 모두 추가해야만 한다. 그리고 selector의 <item>android:state_focused="true" 속성을 추가하면 된다.
  • 안드로이드에서 select와 focus의 차이점이 무엇일까? 읽고 정리해서 업로드하자
  • drawable>shape에서 왜 size가 적용이 안될까.. 내일까지 꼭 방법을 찾을것이다.