πŸ“‹ Kotlin을 μ •λ³΅ν•΄λ΄…μ‹œλ‹€ 1


μ½”ν‹€λ¦°μ΄λž€?

  • μžλ°” ν”Œλž«νΌμ—μ„œ λŒμ•„κ°€λŠ” μƒˆλ‘œμš΄ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄
  • κ°„κ²°ν•˜κ³  μ‹€μš©μ 
  • μžλ°” μ½”λ“œμ™€μ˜ μƒν˜Έ μš΄μš©μ„±μ„ μ€‘μ‹œ
  • μ½”ν‹€λ¦° μ»΄νŒŒμΌλŸ¬κ°€ μƒμ„±ν•œ λ°”μ΄νŠΈμ½”λ“œλŠ” 일반적인 μžλ°” μ½”λ“œμ™€ λ˜‘κ°™μ΄ 효율적으둜 μ‹€ν–‰

정적 νƒ€μž… 지정 μ–Έμ–΄

정적 νƒ€μž… μ§€μ •μ΄λž€ λͺ¨λ“  ν”„λ‘œκ·Έλž¨ ꡬ성 μš”μ†Œμ˜ νƒ€μž…μ„ 컴파일 μ‹œμ μ— μ•Œ 수 μžˆλ‹€.
ν”„λ‘œκ·Έλž¨ μ•ˆμ—μ„œ 객체의 ν•„λ“œλ‚˜ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•  λ•Œλ§ˆλ‹€ μ»΄νŒŒμΌλŸ¬κ°€ νƒ€μž…μ„ 검증해쀀닀.

코틀린은 νƒ€μž…μΆ”λ‘ μ„ μ§€μ›ν•˜μ—¬ κ°œλ°œμžκ°€ νƒ€μž… μ„ μ–Έν•΄μ•Όν•˜λŠ” λΆˆνŽΈν•¨μ΄ 쀄어든닀.
맀개 λ³€μˆ˜ 이름 뒀에 맀개 λ³€μˆ˜μ˜ μžλ£Œν˜•μ„ μ“΄λ‹€.

private val PATTERN = Pattern.compile("//(.)\n(.*)")
private const val FIRST_TARGET_STRING = "//"
private const val LAST_TARGET_STRING = "\n"

λ³€μˆ˜ μ„ μ–Έ

  • val : 값이 λ³€κ²½λ˜μ§€ μ•ŠλŠ” λ³€μˆ˜
  • var : 값이 변경될 수 μžˆλŠ” λ³€μˆ˜

블둝이 본문인 ν•¨μˆ˜

fun max(a: Int, b: Int) : Int {
    return if (a > b) a else b
}

식이 본문인 ν•¨μˆ˜

fun max(a: Int, b: Int) : Int = if (a > b) a else b

μ½”ν‹€λ¦° ν•™μŠ΅ ν…ŒμŠ€νŠΈ

named arguments

Crew("μ‹ μ§€ν˜œ", 20, "μ•„λ§ˆμ°Œ")

Crew 객체에 nameκ³Ό nickname ν•„λ“œκ°€ μžˆμ„ λ•Œ μƒμ„±μžμ— μ „λ‹¬ν•˜λŠ” μΈμžλ§Œμ„ λ³΄κ³ λŠ” μ–΄λ–€ λ¬Έμžμ—΄μ΄ μ–΄λ–€ 역할인지 ν—·κ°ˆλ¦΄ 수 μžˆλ‹€.
μ΄λŠ” ν•¨μˆ˜μ˜ μ‹œκ·Έλ‹ˆμ²˜λ₯Ό μ‚΄νŽ΄λ³΄μ§€ μ•Šκ³ λŠ” μ•Œμ•„λ‚΄κΈ° μ–΄λ €μš΄λ°,
μ½”ν‹€λ¦°μœΌλ‘œ μž‘μ„±ν•œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•ŒλŠ” 가독성을 높이기 μœ„ν•΄ μ „λ‹¬ν•˜λŠ” 인자의 이름을 λͺ…μ‹œν•΄μ€„ 수 μžˆλ‹€.
μ΄λ•Œ 인자 쀑 μ–΄λŠ ν•˜λ‚˜λΌλ„ 이름을 λͺ…μ‹œν•˜λ©΄ κ·Έ λ’€λ‘œ μ˜€λŠ” λͺ¨λ“  μΈμžλŠ” 이름을 λͺ…μ‹œν•΄μ•Ό ν•œλ‹€.

Person("μ‹ μ§€ν˜œ", 20, nickname = "μ•„λ§ˆμ°Œ"),
Person(name = "μ‹ μ§€ν˜œ", nickname = "μ•„λ§ˆμ°Œ", age = 20)

nullable types

class Person(val name: String, val age: Int?, var nickname: String?)

null이 될수 μžˆλŠ” type을 λͺ…μ‹œμ μœΌλ‘œ ν‘œμ‹œν•  수 μžˆλ‹€.
type에 ?λ₯Ό λΆ™μž„μœΌλ‘œμ„œ null이 κ°€λŠ₯ν•œ λ³€μˆ˜μž„μ„ λͺ…μ‹œμ μœΌλ‘œ ν‘œν˜„ν•œλ‹€.

default arguments

class Person(val name: String, val age: Int? = null, var nickname: String? =null)

μžλ°”λŠ”μ˜€λ²„λ‘œλ”©μ„ ν•˜μ—¬ μΈμžκ°€ λ‹€λ₯Έ 같은 λ©”μ„œλ“œλ₯Ό λ§Œλ“ λ‹€.

ν•˜μ§€λ§Œ 코틀린은 κΈ°λ³Έ 인자λ₯Ό μ§€μ›ν•˜κΈ° λ•Œλ¬Έμ—, 1개의 λ©”μ†Œλ“œλ§Œ μ •μ˜ν•˜μ—¬ λ©”μ„œλ“œ μ˜€λ²„λ‘œλ”© κΈ°λŠ₯을 ν•œλ‹€. κΈ°λ³Έ 인자λ₯Ό μ„€μ •ν•˜λŠ” 방법은, λ‹€μŒκ³Ό 같이 인자 이름 λ‹€μŒμ— 인자 = κΈ°λ³Έκ°’μ²˜λŸΌ μ •μ˜ν•˜λ©΄ λœλ‹€.

fun add(num1, num2: Int = 0)

μœ„μ˜ λ©”μ†Œλ“œλŠ” μ•„λž˜μ²˜λŸΌ 인자의 κ°œμˆ˜κ°€ λ‹€λ₯΄κ²Œ 호좜될 수 μžˆμŠ΅λ‹ˆλ‹€.

add(1)      // num2 = 0 은 기본인자둜 전달
add(1, 2)

data classe

data class Person(val name: String, val age: Int? = null, var nickname: String? =null)
  • 수리 ν”Όμ…œ 데이터 ν΄λž˜μŠ€λŠ” DTOλ‹€.
  • λ”±νžˆ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ°–κ³  μžˆμ§€μ•Šλ‹€.
  • μƒμ„±μžλΆ€ν„° getter & setter, 심지어 canonical methodsκΉŒμ§€ μ•Œμ•„μ„œ 생성해쀀닀.

μ œν•œ 사항

  • κΈ°λ³Έ μƒμ„±μžμ—λŠ” μ΅œμ†Œ ν•˜λ‚˜μ˜ νŒŒλΌλ―Έν„°κ°€ μžˆμ–΄μ•Ό ν•œλ‹€.
  • κΈ°λ³Έ μƒμ„±μžμ˜ νŒŒλΌλ―Έν„°λŠ” valμ΄λ‚˜ varμ—¬μ•Όλ§Œ ν•œλ‹€.
  • 데이터 ν΄λž˜μŠ€λŠ” abstract, open, sealed, innerκ°€ 되면 μ•ˆ λœλ‹€.

πŸ€” Canonical Methods?

μΊλ…Έλ‹ˆμ»¬ λ©”μ†Œλ“œλŠ” Any에 μ„ μ–Έλœ λ©”μ†Œλ“œ (AnyλŠ” μžλ°”μ˜ Object처럼 μ½”ν‹€λ¦°μ—μ„œ λͺ¨λ“  객체의 쑰상이 λ˜λŠ” 객체)
λ”°λΌμ„œ μ½”ν‹€λ¦°μ˜ λͺ¨λ“  μΈμŠ€ν„΄μŠ€κ°€ κ°–κ³  μžˆλŠ” λ©”μ†Œλ“œλ₯Ό λœ»ν•œλ‹€.

μ½”ν‹€λ¦°μ˜ data classλŠ” λͺ¨λ“  Canonical λ©”μ„œλ“œλ₯Ό μ˜¬λ°”λ₯΄κ²Œ κ΅¬ν˜„ν•˜κ³  μžˆλ‹€.

  • equlas(other: Any?): Boolean - 이 λ©”μ†Œλ“œλŠ” μ°Έμ‘°κ°€ μ•„λ‹ˆλΌ 데이터 클래슀 κ°„ κ°’μ˜ 일치λ₯Ό λΉ„κ΅ν•œλ‹€.
  • hashCode(): Int - ν•΄μ‰¬μ½”λ“œλŠ” μΈμŠ€ν„΄μŠ€μ˜ 숫자 ν‘œν˜„μ΄λ‹€. hashCode()κ°€ 같은 μΈμŠ€ν„΄μŠ€μ—μ„œ μ—¬λŸ¬ 번 호좜될 λ•Œ 항상 λ™μΌν•œ 값을 λ°˜ν™˜ν•΄μ•Ό ν•œλ‹€. equals()둜 비ꡐ할 λ•Œ 참을 λ°˜ν™˜ν•˜λŠ” 두 μΈμŠ€ν„΄μŠ€λŠ” 같은 hashCode()λ₯Ό κ°€μ Έμ•Όλ§Œ ν•œλ‹€.
  • toString(): String - μΈμŠ€ν„΄μŠ€μ˜ λ¬Έμžμ—΄ ν‘œν˜„μ΄λ‹€. 데이터 ν΄λž˜μŠ€λŠ” 이λ₯Ό 멀버 λ³€μˆ˜μ˜ 값을 λ‚˜μ—΄ν•˜λ„λ‘ μžλ™μœΌλ‘œ μž¬μ •μ˜ ν•œλ‹€.
  • copy() : 객체λ₯Ό λ³΅μ‚¬ν•˜μ—¬ μƒˆ 객체 생성
  • componentsN() : 속성을 μˆœμ„œλŒ€λ‘œ λ°˜ν™˜

2단계 λ¬Έμžμ—΄ 계산기 κ΅¬ν˜„ν•˜λ©΄μ„œ 배운 사싀듀

λ©”μ„œλ“œ μ •μ˜

fun λ©”μ„œλ“œλͺ…(x: Int): λ°˜ν™˜νƒ€μž… {
    retunr 2 * x
}

Unit / Nothing

코틀린은 μ›μ‹œνƒ€μž…κ³Ό wrapper type을 κ΅¬λΆ„ν•˜μ§€ μ•ŠλŠ”λ‹€.

Unit

ν•¨μˆ˜μ˜ λ°˜ν™˜ ꡬ문이 μ—†λ‹€λŠ” 것을 ν‘œν˜„ν•œλ‹€. (μžλ°”μ˜ void에 ν•΄λ‹Ή).
voidμ™€λŠ” λ‹€λ₯΄κ²Œ μΈμžλ‘œλ„ μ‚¬μš©ν•  수 μžˆλ‹€.

Nothing

ν•¨μˆ˜κ°€ μ •μƒμ μœΌλ‘œ λλ‚˜μ§€ μ•ŠλŠ”λ‹€λΌλŠ”κ±Έ λͺ…μ‹œμ μœΌλ‘œ ν‘œν˜„ν•œλ‹€.

firstOrNull

μ»¬λ ‰μ…˜ λ‚΄ 첫 번째 인자λ₯Ό λ°˜ν™˜ν•œλ‹€. λ‹¨μˆœνžˆ 리슀트 λ‚΄μ—μ„œ 첫 λ²ˆμ§Έμ— μœ„μΉ˜ν•˜λŠ” 인자λ₯Ό λ°˜ν™˜ν•˜λŠ” 것뿐 μ•„λ‹ˆλΌ, νŠΉμ • 쑰건을 λ§Œμ‘±ν•˜λŠ” 첫 번째 인자λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ κ΅¬μ„±ν•˜λŠ” 것도 κ°€λŠ₯ν•˜λ‹€.

val operator = values().firstOrNull { item -> item.op == op }
    ?: throw IllegalArgumentException("μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μ—°μ‚°μžμž…λ‹ˆλ‹€.")

μžλ™μ°¨ κ²½μ£Ό ν”Όλ“œλ°±

μ½”ν‹€λ¦°μ˜ μ½”λ”© μ»¨λ²€μ…˜

클래슀

  • ν”„λ‘œνΌν‹°
  • μ΄ˆκΈ°ν™” 블둝
  • λΆ€ μƒμ„±μž
  • ν•¨μˆ˜
  • λ™λ°˜ 객체

순으둜 μž‘μ„±ν•œλ‹€.

βž• ktlint μ μš©ν•˜κΈ°

ktlintλž€ 코틀린을 μœ„ν•œ 정적 뢄석 λ„κ΅¬λ‘œ, μ½”ν‹€λ¦°μœΌλ‘œ μž‘μ„±ν•œ μ½”λ“œμ˜ μŠ€νƒ€μΌ 검사와, ν˜•μ‹μ— λ§žμ§€ μ•ŠλŠ” 뢀뢄을 μˆ˜μ •ν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.

μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ‹€μŒκ³Ό 같이 ν”ŒλŸ¬κ·ΈμΈμ„ μΆ”κ°€ν•΄μ€€λ‹€.

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.3.72'
    id 'org.jmailen.kotlinter' version "3.2.0" // μΆ”κ°€
}

ν”ŒλŸ¬κ·ΈμΈμ„ μΆ”κ°€ν•˜λ©΄ gradle-Tasks-formating이 μƒμ„±λ˜λŠ”λ° lintKotlin을 눌러주면 lint둜 μ½”ν‹€λ¦° μ»¨λ²€μ…˜μ΄ ν‹€λ¦° 뢀뢄을 μž‘μ•„μ€€λ‹€.

μ£Όμƒμ„±μž, λΆ€ μƒμ„±μž

μ£Ό μƒμ„±μž

class Car(val name: String, val position: Int = 0)

클래슀 이름 뒀에 μ˜€λŠ” μƒμ„±μžκ°€ λ°”λ‘œ μ£Ό μƒμ„±μžμ΄λ‹€.
μ£Ό μƒμ„±μžλŠ” μƒμ„±μž νŒŒλΌλ―Έν„°λ₯Ό μ§€μ •ν•˜κ³ , 이에 μ˜ν•΄ μ΄ˆκΈ°ν™”λ˜λŠ” ν”„λ‘œνΌν‹°λ₯Ό μ •μ˜ν•˜λŠ”λ° μ‚¬μš©λœλ‹€.
λ˜ν•œ μ£Ό μƒμ„±μžλŠ” 객체 μ΄ˆκΈ°ν™”λ₯Ό μ‹œμž‘ν•˜λŠ” μœ μΌν•œ 곳이기 λ•Œλ¬Έμ— μ œκ³΅λ˜λŠ” μΈμžλ“€μ΄ μ™„μ „ν•΄μ•Ό ν•œλ‹€.

μ£Ό μƒμ„±μžμ—λŠ” λ³„λ„μ˜ μ½”λ“œλ₯Ό ν¬ν•¨μ‹œν‚¬ 수 μ—†λ‹€.
μ΄λ•Œ 코틀린은 init ν‚€μ›Œλ“œλ‘œ μ΄ˆκΈ°ν™” 블둝을 μ„ μ–Έν•  수 μžˆλ‹€.

class Car(val name: String, val position: Int = 0) {

    init {
        require(name.length <= MAX_NAME_LENGTH) {
            "μžλ™μ°¨μ˜ 이름은 5κΈ€μžλ₯Ό μ΄ˆκ³Όν•  수 μ—†μŠ΅λ‹ˆλ‹€."
        }
    // ...

λΆ€ μƒμ„±μž

νŒŒλΌλ―Έν„° λͺ©λ‘μ΄ λ‹€λ₯Έ μ—¬λŸ¬ μƒμ„±μžλ₯Ό λ§Œλ“€ 경우 λΆ€ μƒμ„±μžλ₯Ό λ‘˜ 수 μžˆλ‹€.
λΆ€ μƒμ„±μžμ—μ„œλŠ” this ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄ μ£Ό μƒμ„±μžλ₯Ό ν˜ΈμΆœν•˜λ„λ‘ ν•œλ‹€.

class Car(val name: String, var position: Int) {
    constructor(name: String) : this(name, 0)
}

ν•˜μ§€λ§Œ 이 κ²½μš°λ³΄λ‹€λŠ” defaultν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ λ§€κ°œλ³€μˆ˜μ˜ 기본값을 μ‚¬μš©ν•˜μž.

μ£Ό μƒμ„±μž 호좜 μ‹œμ 

constructor(carNUm : Int) : this(ArryaList()) {
	createList(carName)
}

μœ„μ™€ 같이 λΆ€ μƒμ„±μžμ—μ„œ μ£Ό μƒμ„±μžλ₯Ό ν˜ΈμΆœν•  λ•Œ createList()κ°€ μ‹€ν–‰λ˜λŠ” μˆœμ„œλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

public Cars(int carNUm) {
  this(new ArrayList())
  this.createList(carNum)
}

require(), check() - 쑰건 확인 ν•¨μˆ˜

  • require() : 식이 참이 아닐 경우 IllegalArgumentException λ°œμƒ

  • check() : 식이 참이 아닐 경우 IllegalStateException λ°œμƒ

    μœ„ 예제처럼 {} 블둝에 μ˜ˆμ™Έ λ©”μ‹œμ§€λ₯Ό μž‘μ„±ν•  μˆ˜λ„ μžˆλ‹€.

setter만 private으둜 - κ°€μ‹œμ„± λ³€κ²½μž

μžλ°”λ₯Ό μƒκ°ν•˜λ©΄ ν•„λ“œλ₯Ό private 둜 λ§Œλ“€κ³ , getterλ₯Ό 톡해 값을 꺼내도둝 ν•˜μ˜€μ§€λ§Œ,
μ½”ν‹€λ¦°μ—μ„œλŠ” ν•„λ“œλ₯Ό private으둜 λ‘κΈ°λ³΄λ‹€λŠ” setter ν•¨μˆ˜λ§Œ private으둜 μ§€μ •ν•œλ‹€.

class Car(val name: String) {
    var position: Int = 0
        private set
}

μžλ°”λŠ” ν•„λ“œ 기반 언어인데 코틀린은 ν”„λ‘œνΌν‹° 기반 언어이닀.
νŒμ„ μ€€λ‹€λ©΄ μ½”ν‹€λ¦°μ—μ„œ ν”„λ‘œνΌν‹°μ— 무언가 연산이 λ“€μ–΄κ°„λ‹€λ©΄ ν•¨μˆ˜λ₯Ό λ§Œλ“€κ³ ,
κ°’ 자체만 λ°˜ν™˜ν•œλ‹€λ©΄ μœ„μ™€ 같이 μ“°μž.

μƒμˆ˜

κΈ°λ³Έ μžλ£Œν˜•μ˜ μƒμˆ˜λŠ” const val ν‚€μ›Œλ“œλ‘œ ν‘œν˜„ν•œλ‹€.
κΈ°λ³Έ μžλ£Œν˜• μ™Έμ—λŠ” const ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•  수 μ—†λ‹€.

μƒμˆ˜λŠ” 클래슀 외뢀에닀가도 μ„ μ–Έν•  수 μžˆλ‹€.
ν•˜μ§€λ§Œ 이 경우 ν™•μž₯μžκ°€ 파일둜 λ³€κ²½λ˜λ‹ˆ μ‚¬λžŒ μ·¨ν–₯껏 ν•˜λ©΄ λœλ‹€.

companion object - λ™λ°˜ 객체

μ½”ν‹€λ¦°μ—μ„œλŠ” static ν‚€μ›Œλ“œκ°€ μ—†λŠ”λ°, 이 λŒ€μ‹  μ‚¬μš©ν•  수 μžˆλŠ” 것이 companion object 이닀.
μ΄λŠ” 객체이며, companion object 내에 μ„ μ–Έλœ 속성과 ν•¨μˆ˜λŠ” {클래슀 이름}.{ν•„λ“œ/ν•¨μˆ˜ 이름} ν˜•νƒœλ‘œ λ°”λ‘œ ν˜ΈμΆœν•  수 μžˆλ‹€.
클래슀의 맨 ν•˜λ‹¨μ— μž‘μ„±ν•œλ‹€.

@JvmStatic

ompanion objectλ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬μ„±ν•œ μ½”λ“œλ₯Ό μžλ°”μ—μ„œ μ‚¬μš©ν•˜λ €λ©΄ 속성 및 ν•¨μˆ˜κ°€ μžλ°”μ˜ ν•„λ“œ/λ©”μ„œλ“œλ‘œ ν•΄μ„λ˜λ„λ‘ μ•Œλ €μ£Όμ–΄μ•Ό ν•œλ‹€.

const 선언이 λ˜μ–΄ μžˆλŠ” ν”„λ‘œνΌν‹°λŠ” λ³„λ„μ˜ 처리 없이 μžλ°”μ—μ„œλ„ μ‚¬μš© κ°€λŠ₯ν•˜λ©°, ν•¨μˆ˜λŠ” @JvmStatic μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜μ—¬ μžλ°”μ—μ„œ 정적 λ©”μ„œλ“œλ‘œ μ‚¬μš©ν•  수 있게 ν•œλ‹€.

@JvmField

const ν‚€μ›Œλ“œλŠ” κΈ°λ³Έ μžλ£Œν˜•μ—λ§Œ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€.
μ΄μ™Έμ˜ νƒ€μž… 객체λ₯Ό μžλ°”μ—μ„œ 정적 ν•„λ“œμ²˜λŸΌ μ‚¬μš©ν•˜λ €λ©΄ @JvmField μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.

Utility 클래슀

μžλ°”μ—μ„œλŠ” λͺ¨λ“  λ©”μ„œλ“œλ₯Ό 클래슀 내뢀에 μž‘μ„±ν•΄μ•Όν–ˆμ§€λ§Œ, μ½”ν‹€λ¦°μ—μ„œλŠ” 그럴 ν•„μš”κ°€ μ—†λ‹€.
ν•„μš”ν•œ μœ ν‹Έλ¦¬ν‹° λ©”μ„œλ“œλ§Œ λͺ¨μ•„놓은 νŒŒμΌλ§Œμ„ λ§Œλ“€κ³  이λ₯Ό 파일 μ΅œμƒμœ„μ— μœ„μΉ˜μ‹œν‚€λ©΄ λœλ‹€.

슀마트 캐슀트

μ½”ν‹€λ¦°μ—μ„œλŠ” μ»΄νŒŒμΌλŸ¬κ°€ λŒ€μ‹  μΊμŠ€νŒ…μ„ ν•΄μ€€λ‹€.
μ›ν•˜λŠ” νƒ€μž…μ„ κ²€μ‚¬ν•˜κ³  λ‚˜λ©΄, κ°œλ°œμžκ°€ λ³€μˆ˜λ₯Ό μ›ν•˜λŠ” νƒ€μž…μœΌλ‘œ μΊμŠ€νŒ…ν•˜μ§€ μ•Šμ•„λ„ ν•΄λ‹Ή λ³€μˆ˜κ°€ μ›ν•˜λŠ” νƒ€μž…μœΌλ‘œ μ„ μ–Έλœ κ²ƒμ²˜λŸΌ μ‚¬μš©ν•  수 μžˆλ‹€.
μ΄λŠ” μ»΄νŒŒμΌλŸ¬κ°€ μΊμŠ€νŒ…μ„ μˆ˜ν–‰ν•΄μ£Όμ–΄ κ°€λŠ₯ν•œ 일이닀.

fun calculate(text: String?): Int {
    if (text.isNullOrBlank()) {
        throw IllegalArgumentException()
    }
    val tokens = text.split(" ")
    // ...
}

μ½”λ“œ 리뷰 쀑 μ§€λ§‰ν•œ 배움

maxBy{}

fun findMaxPosition(): Int {
        return cars.maxBy { it.position }!!.position
    }

κ°€μž₯ 큰 μ›μ†Œλ₯Ό μ°ΎκΈ° μœ„ν•΄ 비ꡐ에 μ‚¬μš©ν•  값을 인자둜 λ°›λŠ”λ‹€.
λͺ¨λ“  μ»¬λ ‰μ…˜μ— λŒ€ν•΄ maxBy ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  수 μžˆλ‹€.

{ it.position } λŠ” 비ꡐ에 μ‚¬μš©ν•  값을 λŒλ €μ£ΌλŠ” ν•¨μˆ˜μ΄λ‹€.
maxBy{} 의 λ°˜ν™˜ 값은 nullable인데, λ°˜ν™˜λœ κ°’μ˜ ν”„λ‘œνΌν‹°λ₯Ό μ‚¬μš©ν•˜κ³  싢은 경우 !! ν‚€μ›Œλ“œλ₯Ό 톡해 null이 μ•„λ‹˜μ„ μ„ μ–Έν•˜μ—¬ κΊΌλ‚Έλ‹€.

μ°Έκ³ 

?:(μ—˜λΉ„μŠ€ μ˜€νΌλ ˆμ΄ν„° ) : null인 경우 μ„€μ •ν•œ default 값을 λ„£λŠ”λ‹€.

Pair

Kotlinμ—μ„œ μ œκ³΅ν•˜λŠ” 객체 νƒ€μž… 쀑 μ—°κ΄€ νƒ€μž…λΌλ¦¬ 관계가 없어도 2개λ₯Ό 쌍으둜 가지고 μžˆλŠ” 객체

getterλŠ” .first .second λ˜λŠ” .component1() / .component2()둜 μ ‘κ·Όν•  수 μžˆλ‹€.

RacingCar 일뢀

fun race(moveStrategy: MoveStrategy): Pair<List<Cars>, List<Car>> {
    val carsGroup = arrayListOf<Cars>()
    for (i in 0 until tryNumber) {
        this.cars = this.cars.moveAll(moveStrategy)
        carsGroup.add(this.cars)
    }
    return Pair(carsGroup, findWinners())
}

private fun findWinners(): List<Car> {
    val maxPosition = cars.findMaxPosition()
    return cars.findCarsBySamePosition(maxPosition)
}

==κ³Ό ===

  • == μ—°μ‚°μžλŠ” μžλ°”μ˜ equal와 κ°™λ‹€.

  • === μ—°μ‚°μžλŠ” μžλ°”μ˜ ==와 κ°™λ‹€.

List, MutableList

μ½”ν‹€λ¦°μ—μ„œλŠ” 읽기 μ „μš© 리슀트(List)와 μˆ˜μ •ν•  수 μžˆλŠ” 리슀트(MutableList)κ°€ μžˆλ‹€.
arrayListOf() λ₯Ό μ“°κΈ°λ³΄λ‹€λŠ” 코틀린이 μ œκ³΅ν•˜λŠ” List λ˜λŠ” MutableListλ₯Ό μ‚¬μš©ν•˜μž

List

데이터λ₯Ό 읽기만 κ°€λŠ₯ν•˜κ³  리슀트λ₯Ό μ„ μ–Έν•  λ•Œ 넣은 데이터듀을 μˆ˜μ •, μ‚­μ œ, λ³€κ²½ν•  수 μ—†λ‹€.

var cars = listOf(Car("ama"), Car("mazzi"))

println(cars[0]) // O

cars.add(Car("new")) // X μ»΄νŒŒμΌμ—λŸ¬
cars.remove(1)   // X μ»΄νŒŒμΌμ—λŸ¬

MutableList

κΈ°μ‘΄ μžλ°”μ—μ„œ μ‚¬μš©ν•˜λ˜ ArrayList와 μœ μ‚¬ν•˜λ―€λ‘œ ArrayList의 ν•¨μˆ˜λ“€μ„ λͺ¨λ‘ μ‚¬μš©ν•  수 μžˆλ‹€.

var carsMutable = mutableListOf<Car>()
carsMutable.add(Car("ama")) // O
carsMutable.add(Car("mazzi")) // O
carsMutable.remove(0) // O
println(carsMutable[0]) // O

List와 MutalbeList μ„œλ‘œμ˜ νƒ€μž…μœΌλ‘œ 변경도 κ°€λŠ₯ν•˜λ‹€. 이 λ•Œ μ„œλ‘œ μƒˆλ‘œμš΄ 리슀트λ₯Ό λ°˜ν™˜ν•œλ‹€.

var carsMutable = mutableListOf<Car>()
carsMutable.add(Car("ama")) 
carsMutable.add(Car("mazzi")) 

var arrNotMutable = carsMutable.toList() //mutable -> list λ³€κ²½

var arrReMutable = arrNotMutable.toMutableList() // list -> mutable λ³€κ²½
arrReMutable.add(Car("new"))
println(arrReMutable)

assertThrows

μžλ°”μ²˜λŸΌ assertThatThrownBy λ₯Ό 쓰지 말고 μ•„λž˜μ™€ 같이 μ“°μž.
μ΄μœ λŠ” assertThatThrownBy λ₯Ό μ‚¬μš©ν•  경우 isInstanceOf() λ₯Ό μ‚¬μš©ν•˜λŠ”λ° μ—¬κΈ°μ—λŠ” .java.class λ₯Ό λΆ™μ—¬μ£Όμ–΄μ•Ό ν•΄ μ½”ν‹€λ¦° μŠ€λŸ½μ§€ λͺ»ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

<IllegalArgumentException> {Car(name = input)}

object

클래슀λ₯Ό λ§Œλ“¦κ³Ό λ™μ‹œμ— μΈμŠ€ν„΄μŠ€λ‘œ λ§Œλ“ λ‹€. (μ‹±κΈ€ν„΄)

λžŒλ‹€ μž‘μ„±

코틀린은 λžŒλ‹€μ‹μ„ μž‘μ„±ν•  λ•Œ {}둜 ν‘œν˜„ν•œλ‹€.
λžŒλ‹€μ˜ μΈμžκ°€ ν•˜λ‚˜λΌλ©΄ λžŒλ‹€μ‹ λ‚΄λΆ€μ—μ„œ it으둜 받을 수 μžˆλ‹€.
ν•¨μˆ˜μ˜ 인자둜 λžŒλ‹€κ°€ λ„˜μ–΄μ˜¬ λ•Œ, 맨 λ§ˆμ§€λ§‰ 순번이라면 () 밖에 μ“Έ 수 μžˆλ‹€.
λ§Œμ•½ λžŒλ‹€ ν•˜λ‚˜λ§Œ λ°›λŠ” 거라면 ()λ₯Ό μƒλž΅ν•  수 있겠죠?

val newCars = cars.map { it.move(moveStrategy) }

associate{}

map을 기본적으둜 λ°˜ν™˜ν•œλ‹€.

Input을 μž¬κ·€μ μœΌλ‘œ

tailrec fun inputCarNames(): List<String> {
    println("κ²½μ£Όν•  μžλ™μ°¨ 이름을 μž…λ ₯ν•˜μ„Έμš”(이름은 μ‰Όν‘œ(,)λ₯Ό κΈ°μ€€μœΌλ‘œ ꡬ뢄).")
    return readLine()?.replace(" ", "")?.split(",") ?: inputCarNames()
}

tailrec fun inputTryNumber(): Int {
    println("μ‹œλ„ν•  νšŸμˆ˜λŠ” λͺ‡ νšŒμΈκ°€μš”?")
    return readLine()?.toIntOrNull() ?: inputTryNumber()
}
  • tailrec : κΌ¬λ¦¬μž¬κ·€(tail recursive)λΌλŠ” 의미둜, 좔가적인 연산이 없이 μžμ‹  슀슀둜 μž¬κ·€μ μœΌλ‘œ ν˜ΈμΆœν•˜λ‹€κ°€ μ–΄λ–€ 값을 λ¦¬ν„΄ν•˜λŠ” ν•¨μˆ˜
    • ν•΄λ‹Ή ν‚€μ›Œλ“œλ₯Ό 뢙이면 μž¬κ·€μ μΈ ν•¨μˆ˜ 호좜의 μ΅œμ ν™”κ°€(?) 일어남

μ€‘μœ„ ν•¨μˆ˜ (to ν‚€μ›Œλ“œ)

  • μ€‘μœ„ ν‘œν˜„λ²• : λ³€μˆ˜μ™€ λ³€μˆ˜μ‚¬μ΄μ— ν•¨μˆ˜λ₯Ό λ„£μ–΄ μ—°μ‚°μž 처럼 μ‚¬μš©ν•˜λŠ” 것

쑰건

  • 멀버 λ©”μ„œλ“œ λ˜λŠ” ν™•μž₯ ν•¨μˆ˜μ—¬μ•Ό 함
  • ν•˜λ‚˜μ˜ λ§€κ°œλ³€μˆ˜λ₯Ό 가져야함
  • infix ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ •μ˜

ex) Pair 객체λ₯Ό 생성할 λ•Œ to

by ν‚€μ›Œλ“œ

μœ„ μ½”λ“œμ—μ„œ Car의 일급 μ»¬λ ‰μ…˜μΈ Carsλ₯Ό μˆœνšŒν•  λ•Œ ν˜„μž¬λŠ” List<Car>에 μ ‘κ·Όν•˜μ—¬ μˆœνšŒν•˜κ³  μžˆλ‹€.
ν•˜μ§€λ§Œ μ½”ν‹€λ¦°μ—μ„œλŠ” λ‹€μŒκ³Ό 같이 λ³€κ²½ν•  수 μžˆλ‹€.

μœ„μ™€ 같이 cars 일급 μ»¬λ ‰μ…˜μ„ λ°”λ‘œ μˆœνšŒν•  수 μžˆλŠ” μ΄μœ λŠ” Carsκ°€ λ‹€μŒκ³Ό 같이 List<Car> μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜κ³  있기 λ•Œλ¬Έμ΄λ‹€.

뭐야 μ™„μ „ 신기해….
제이슨이 일단 μ§€κΈˆμ€ β€œμ™€ 뭐야” μ΄μ •λ„κΉŒμ§€λ§Œ μ•Œμ•„λ‘μ–΄λ„ λœλ‹€κ³  ν•˜μ˜€λ‹€.
μ½”ν‹€λ¦° 짱