일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 27 | 28 |
- Rxjava Observable
- 서비스 쓰레드 차이
- ar vr 차이
- rxjava hot observable
- 안드로이드 라이선스
- 클래스
- 안드로이드 라이선스 종류
- android ar 개발
- 안드로이드 유닛 테스트
- 2022 플러터 안드로이드 스튜디오
- 안드로이드 레트로핏 사용법
- 안드로이드 유닛 테스트 예시
- 서비스 vs 쓰레드
- rxjava cold observable
- 큐 자바 코드
- 스택 자바 코드
- jvm 작동 원리
- android retrofit login
- 2022 플러터 설치
- 객체
- 플러터 설치 2022
- ANR이란
- 안드로이드 os 구조
- 자바 다형성
- 안드로이드 레트로핏 crud
- 멤버변수
- 안드로이드 유닛테스트란
- jvm이란
- 스택 큐 차이
- rxjava disposable
- Today
- Total
목록책/Effective Kotlin (53)
나만을 위한 블로그
메서드를 정의할 때는 메서드를 멤버로 정의할지 확장 함수로 정의할지를 결정해야 한다. 두 방법은 거의 비슷하다. 호출법도 비슷하고 리플렉션으로 레퍼런싱하는 방법도 비슷하다. 두 방식 중에 어떤 방식이 우월하다곤 할 수 없다. 상황에 맞게 사용해야 한다. 멤버와 확장의 가장 큰 차이점은 확장은 따로 가져와서 써야 한다는 것이다. 그래서 일반적으로 확장은 다른 패키지에 위치한다. 확장은 내가 직접 멤버를 추가할 수 없는 경우 데이터와 행위를 분리하게 설계된 프로젝트에서 쓰인다. 필드가 있는 프로퍼티는 클래스에 있어야 하지만 메서드는 클래스의 public API만 쓴다면 어디 있어도 상관없다. 임포트해서 쓴다는 특징 때문에 확장은 같은 타입에 같은 이름으로 여러 개 만들 수도 있다. 따라서 여러 라이브러리에서..
compareTo()는 Any 클래스의 메서드가 아니다. 수학적인 부등식으로 변환되는 연산자다. fun main() { obj1 > obj2 // obj1.compareTo(obj2) > 0 obj1 = obj2 // obj1.compareTo(obj2) >= 0 obj1 = a면 a == b여야 한다. 비교와 동등성 비교에 어떤 관계가 있어야 하고 일관성이 있어야 한다 연속적 동작 : a >= b, b >= c면 a >= c여야 한다. 이런 동작을 하지 못하면 요소 정렬이 무한 반복에 빠질 수 있다 코넥스적 동작 : 두 요소는 어떤 확실한 관계를 갖고 있어야 한다. a >= b 또는 b >= a 중에 적어도 하나는 항상 true여..
hashCode()는 수많은 컬렉션, 알고리즘에 사용되는 자료구조인 해시 테이블 구축 시 사용된다. 해시 테이블 컬렉션에 요소를 빠르게 추가하고 추출해야 한다고 친다. 이 때 사용할 수 있는 컬렉션은 Set, Map이 있다. 이들은 중복을 허용하지 않는다. 따라서 요소를 추가할 때 동일한 요소가 이미 들어 있는지 확인해야 한다. 배열 또는 링크드 리스트 기반으로 만들어진 컬렉션은 요소가 포함돼 있는지 확인하는 성능이 좋지 않다. 수백만 개의 텍스트가 포함된 배열에 특정 텍스트가 포함돼 있는지 확인해야 할 경우, 수백만 개의 텍스트를 선형으로 비교한다면 꽤 오랜 시간이 걸릴 것이다. 성능을 좋게 만드는 해결법이 해시 테이블이다. 해시 테이블은 각 요소에 숫자를 할당하는 함수가 필요하다. 이 함수를 해시 함..
코틀린의 Any에는 잘 설정된 규약을 가진 아래 메서드들이 있다. equals hashCode toString 이런 메서드들의 규약은 주석, 문서에 잘 설명돼 있다. 아이템 32에서 설명한 것처럼 Any 클래스를 상속받는 모든 메서드는 이런 규약을 잘 지키는 게 좋다. 동등성(equality) 코틀린에는 2가지 동등성이 있다. 구조적 동등성 : equals 메서드와 이를 기반으로 만들어진 !=, == 연산자로 확인하는 동등성이다. a가 nullable이 아니면 a == b는 a.equals(b)로 변환되고, a가 nullable이면 a?.equals(b) ?: (b === null)로 변환된다 레퍼런스적 동등성 : !==, === 연산자로 확인하는 동등성이다. 두 피연산자가 같은 객체를 가리키면 true..
큰 규모의 프로젝트에선 상수(constant) 모드를 가진 클래스를 꽤 많이 볼 수 있다. 이런 상수 모드를 태그라고 부르며 태그를 포함한 클래스를 태그 클래스라고 부른다. 그런데 태그 클래스는 다양한 문제를 갖고 있다. 이런 문제는 서로 다른 책임을 한 클래스에 태그로 구분해서 넣는다는 것에서 시작한다. 아래 코드를 보면 테스트에 쓰이는 클래스로서 어떤 값이 기준에 만족하는지 확인하기 위해 쓰이는 클래스를 볼 수 있다. class ValueMatcher private constructor( private val value: T? = null, private val matcher: Matcher ) { enum class Matcher { EQUAL, NOT_EQUAL, LIST_EMPTY, LIST_N..
대부분 프로그래밍 언어에는 함수 타입이란 개념이 없어서 연산 또는 액션을 전달할 때 메서드가 하나만 있는 인터페이스를 활용한다. 이런 인터페이스를 SAM(Single-Abstract Method)이라고 부른다. 예를 들어 아래 코드는 뷰를 클릭했을 때 발생하는 정보를 전달하는 SAM이다. interface OnClick { fun clicked(view: View) } 함수가 SAM을 받는다면 이런 인터페이스를 구현한 객체를 구현한 객체를 전달받는다는 의미다. fun main() { setOnClickListener(object: OnClick { override fun clicked(view: View) { // ... } }) } fun setOnClickListener(listener: OnClic..
때로는 데이터들을 한꺼번에 전달해야 할 때가 있다. 일반적으로 이런 상황에 아래와 같은 data 한정자가 붙은 클래스를 사용한다. fun main() { val player = Player(0, "철수", 100) } data class Player( val id: Int, val name: String, val points: Int ) data 한정자를 붙이면 몇 가지 함수가 자동 생성된다. toString equals, hashCode copy componentN(1, 2, ...) toString()은 클래스명과 기본 생성자 형태로 모든 프로퍼티와 값을 출력해준다. 로그 출력, 디버그 시 유용하게 쓸 수 있다. equals()는 기본 생성자의 프로퍼티가 같은지 확인한다. hashCode()는 equ..
상속은 굉장히 강력한 기능으로 "is-a" 관계의 객체 계층 구조를 만들기 위해 설계됐다. 상속은 관계가 불명확할 때 쓰면 여러 문제가 발생할 수 있다. 따라서 단순하게 코드 추출 또는 재사용을 위해 상속을 하려고 한다면 좀 더 신중하게 생각해야 한다. 일반적으로 이런 경우에는 상속보다 컴포지션을 쓰는 게 좋다. 간단한 행위 재사용 간단한 코드부터 확인한다. 프로그레스 바를 어떤 로직 처리 전에 출력하고, 처리 후 숨기는 유사한 동작을 하는 2개의 클래스가 있다고 가정한다. class ProfileLoader { fun load () { // 프로그레스 바 표시 // 프로필 읽어들임 // 프로그레스 바 숨김 } } class ImageLoader { fun load() { // 프로그레스 바 표시 // ..
코틀린을 활용하면 DSL(Domain Specific Language)을 직접 만들 수 있다. DSL은 복잡한 객체, 계층 구조를 가진 객체들을 정의할 때 유용하다. DSL을 만드는 건 약간 힘든 일이지만 한 번 만들고 나면 보일러플레이트와 복잡성을 숨기면서 개발자의 의도를 명확하게 표현할 수 있다. 예를 들어 코틀린 DSL은 아래와 같은 형태로 HTML을 표현할 수 있다. 이는 고전적인 HTML, 리액트 HTML 모두에서 활용할 수 있다. body { div { a("https://kotlinlang.org") { target = ATarget.blank + "Main site" } } + "Some content" } 다른 플랫폼의 뷰도 이런 형태로 DSL을 써서 만들 수 있다. DSL은 자료 또는 ..
객체를 정의, 생성하는 방법을 지정할 때 사용하는 가장 기본적인 방법은 기본 생성자를 사용하는 것이다. fun main() { val user = User("김", "철수") } class User(var name: String, var surname: String) 기본 생성자는 편리하다. 따라서 일반적으론 이를 활용해서 객체를 만드는 게 좋다. 기본 생성자로 객체를 만들 때는 객체의 초기 상태를 나타내는 아규먼트를 전달한다. 데이터를 표현하는 가장 기본적인 데이터 모델 객체는 생성자로 상태를 초기화한 뒤 그 프로퍼티를 유지한다. data class Student( val name: String, val surname: String, val age: Int ) 아래 코드는 인덱스가 붙어 있는 글을 출력..