λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Kotlin

Kotlin_μ œλ„€λ¦­ / ν™•μž₯ / ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°

by λ„μΊλ¦¬πŸ± 2021. 7. 2.
λ°˜μ‘ν˜•

μ œλ„€λ¦­ νƒ€μž… ν‘œμ€€ν™”λœ λͺ…μΉ­

 

↓ TakeIf, TakeUnless

https://medium.com/@limgyumin/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%9D%98-takeif-takeunless-%EB%8A%94-%EC%96%B8%EC%A0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EA%B0%80-f6637987780

 

/**
 * generic :
 * ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€ 맀개 λ³€μˆ˜ λ˜λŠ” ν•¨μˆ˜μ˜ 맀개 λ³€μˆ˜ λ°˜ν™˜ νƒ€μž…μ„ 미리 ν™•μ •ν•˜μ§€ μ•Šκ³ 
 * μ •μ˜ν•œ 후에 μ‚¬μš©λ˜λŠ” μ‹œμ μ—μ„œ νŠΉμ • νƒ€μž…μ„ 지정할 수 μžˆλ„λ‘ ν•΄μ£ΌλŠ” 기법이 μ œλ„€λ¦­.
 *
 * μΊμŠ€νŒ…μ„ 방지 ν•˜μ—¬ μ„±λŠ₯ ν–₯상 κ°€λŠ₯.
 *
 * ( ListλŠ” Generic μΈν„°νŽ˜μ΄μŠ€λ‘œ μ •μ˜ 됨 → ν•œ μ’…λ₯˜μ˜ List μ•ˆμ— λ‹€λ₯Έ νƒ€μž…μ˜ μš”μ†Œλ“€μ„ μ €μž₯ν•  수 μžˆλ‹€.)
 *
 * 볡합 μ œλ„€λ¦­ νƒ€μž… λ§€κ°œλ³€μˆ˜
 *
 *
 * μ œλ„€λ¦­ νƒ€μž… μ œμ•½ (type constraint)
 * - μ›ν•˜μ§€ μ•ŠλŠ” νƒ€μž…μ˜ μ•„μ΄ν…œμ€ μ €μž₯ν•˜μ§€ λͺ»ν•˜λŒλ‘ ν•˜κ³  싢을 λ•Œ
 *
 *
 * vararg 와 get
 * : κ°€λ³€μΈμž vararg  ν‚€μ›Œλ“œ - 인자의 개수λ₯Ό κ°€λ³€μ μœΌλ‘œ 전달 κ°€λŠ₯.
 *
 * out ν‚€μ›Œλ“œ : Loot의 μ–΄λ–€ μ„œλΈŒ 클래슀 μΈμŠ€ν„΄μŠ€λ„ κ°€λ³€ 인자둜 받을 수 μžˆλ‹€.
 * >> μ½”ν‹€λ¦°μ—μ„œλŠ” inκ³Ό out ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ œλ„€λ¦­ νƒ€μž… λ§€κ°œλ³€μˆ˜λ₯Ό 더 λ‹€μ–‘ν•œ λ°©λ²•μœΌλ‘œ μ‘°μ •ν•  수 μžˆλ‹€.
 *
 *
 * reified ν‚€μ›Œλ“œ
 *
 * */

// μ œλ„€λ¦­ νƒ€μž… μ •μ˜ν•˜κΈ°
// μ œλ„€λ¦­ νƒ€μž… λ§€κ°œλ³€μˆ˜ T λ₯Ό κ°–λŠ”λ‹€. → μ–΄λ–€ νƒ€μž…μ˜ item도 받을 수 있으며, κ·Έ private 속성인 loot에 μ§€μ •ν•œλ‹€.
// μ–΄λ–€ λ‹¨μ–΄λ‚˜ λ¬Έμžμ—¬λ„ 상관 μ—†μœΌλ‚˜ ν‘œμ€€ν™”λœ λͺ…칭을 λ”°λ₯΄λŠ” 것이 μ’‹λ‹€.

// <T> → <T :  Loot> 둜 νƒ€μž… μ œμ•½ : 즉 LootBoxμ—λŠ” μ–΄λ–€ μ’…λ₯˜μ΄λ“  Loot 만 지정할 수 있음.
// LootBox에 vararg ν‚€μ›Œλ“œλ₯Ό μΆ”κ°€ν•˜λ©΄ λ§€κ°œλ³€μˆ˜κ°€ λ°°μ—΄λ‘œ μ²˜λ¦¬λ˜λ―€λ‘œ μ—¬λŸ¬ 개의 μ•„μ΄ν…œμ„ 인자둜 전달.
class LootBox<T : Loot>(vararg item: T)
{
    var open = false
    // private var loot: T = item
    private var loot: Array<out T> = item

    operator fun get(index : Int):T? = loot[index].takeIf { open }

    // λ§Œμ•½ open 이 false 이면 takeIf μ—μ„œ null을 λ°˜ν™˜ν•˜λ―€λ‘œ T? 둜 νƒ€μž… 지정.
    fun fetch(item: Int): T?{
        // return loot.takeIf{ open }
        return loot[item].takeIf{ open }

    }

    // 볡합 μ œλ„€λ¦­ νƒ€μž… λ§€κ°œλ³€μˆ˜
    fun <R> fetch(item: Int, lootModFunction: (T)->R):R? {
        return lootModFunction(loot[item]).takeIf { open }
    }
}

open class Loot (val value:Int)

// Fedora 와 Coin μ—μ„œ value μ†μ„±μ˜ val을 μ‚­μ œν•œ 이유 : Loot ν΄λž˜μŠ€μ—μ„œ 상속 λ˜λŠ” value 속성을 μ‚¬μš©ν•  것이기 λ•Œλ¬Έ
class Fedora(val name:String,  value: Int) : Loot(value)
class Coin( value: Int) : Loot(value)




fun main() {
//    val lootBoxOne : LootBox<Fedora> = LootBox(Fedora("ν‰λ²”ν•œ μ€‘μ ˆλͺ¨",15))
//    val lootBoxTwo : LootBox<Coin> = LootBox(Coin(15))

//    lootBoxOne.open = true
//    lootBoxOne.fetch()?.run {
//        println("${name} 을 LootBoxμ—μ„œ κΊΌλƒˆμŠ΅λ‹ˆλ‹€.")
//    }
//
//    val fedora = lootBoxOne[1]
//    fedora?.let{println(it.name)}

    // νŒ¨λŸ¬λ―Έν„°λ‘œ λ„˜κΈ΄κ±΄ μΈμŠ€ν„΄μŠ€ A
    UsingGeneric(A()).doShouting()
    UsingGeneric(B()).doShouting()
    UsingGeneric(C()).doShouting()

    doShouting(B())
}

fun <T:A> doShouting(t:T){
    t.shout()
}
open class A{
    open fun shout(){
        println("A κ°€ μ†Œλ¦¬μΉ©λ‹ˆλ‹€.")
    }
}

class B : A()
{
    override fun shout() {
        println("Bκ°€ μ†Œλ¦¬μΉ©λ‹ˆλ‹€.")
    }
}

class C : A()
{
    override fun shout() {
        println("Cκ°€ μ†Œλ¦¬μΉ©λ‹ˆλ‹€.")
    }
}

// 수퍼 클래슀λ₯Ό A둜 μ œν•œν•œ μ œλ„ˆλ¦­ T μ„ μ–Έ
class UsingGeneric<T: A> (val t:T){
    fun doShouting(){
        t.shout()
    }
}

 

 

ν™•μž₯.

/**
 * ν•¨μˆ˜μ˜ ν™•μž₯은 클래슀 상속 없이도 κ°€λŠ₯ν•˜λ‹€.
 *
 * 연쇄 호좜 - μ΄ν›„μ˜ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  수 μžˆλŠ” 객체λ₯Ό 이전 ν•¨μˆ˜ ν˜ΈμΆœμ—μ„œ λ°˜ν™˜ν•œλ‹€λ©΄ μ—°μ†ν•΄μ„œ μ—¬λŸ¬ ν•¨μˆ˜ 호좜 κ°€λŠ₯
 * ν™•μž₯ ν•¨μˆ˜μ— μΆ”κ°€ν•˜μ—¬ ν™•μž₯ 속성도 μ •μ˜ν•  수 μžˆλ‹€.
 *
 * μ‚°μΆœ 속성을 μ œμ™Έν•œ λͺ¨λ“  클래슀 속성은 데이터가 μ €μž₯λ˜λŠ” 후원 ν•„λ“œλ₯Ό 가지며, κ²Œν„°μ™€ μ„Έν„°κ°€ μžλ™ 생성 됨.
 * κ·ΈλŸ¬λ‚˜ ν™•μž₯ 속성은 μ‚°μΆœ 속성 처럼 후원 ν•„λ“œλ₯Ό 갖지 μ•ŠλŠ”λ‹€.λ”°λΌμ„œ μ†μ„±μ—μ„œ λ°˜ν™˜λ  값을 μ‚°μΆœ ν•˜λŠ” get 을 λ°˜λ“œμ‹œ μ •μ˜ν•΄μ•Ό 함.
 *
 * 예λ₯Ό λ“€μ–΄ μ•„λž˜ μ½”λ“œλŠ” 컴파일 μ—λŸ¬. Why? ν™•μž₯ 속성은 후원 ν•„λ“œλ₯Ό 갖지 μ•ŠμœΌλ―€λ‘œ μ΄ˆκΈ°ν™”ν•  수 μ—†κΈ° λ•Œλ¬Έ.
 * var String.preferredCharacters = 10
 * λ”°λΌμ„œ var λŒ€μ‹  val 을 μ§€μ •ν•˜κ³  μ›ν•˜λŠ” 값을 λ°˜ν™˜ν•˜λŠ” get 을 μ •μ˜ν•΄μ•Ό ν•œλ‹€.
 *
 *
 * μ½”ν‹€λ¦°μ˜ λͺ¨λ“  μ»¬λ ‰μ…˜ ν΄λž˜μŠ€μ™€ μΈν„°νŽ˜μ΄μŠ€μ˜ 슈퍼 νƒ€μž…μ€ Iterable 이닀.
 *
 *
 * 1. μƒˆλ‘œμš΄ "extension"폴더λ₯Ό λ§Œλ“ λ‹€.
 * 2. ν•΄λ‹Ή 폴더 μ•ˆμ˜ .kt νŒŒμΌμ— private ν™•μž₯ ν•¨μˆ˜λ₯Ό μž…λ ₯ν•œλ‹€.
 * 3. private 을 μ—†μ•€λ‹€.
 * 4. ν•΄λ‹Ή ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜κ³  싢은 λ‹€λ₯Έ μ™ΈλΆ€μ˜ .kt νŒŒμΌμ—μ„œ import λ₯Ό ν•΄μ€€λ‹€.
 * 5. import 주의 사항! import 문을 μ‚¬μš©ν•˜κ³ μž ν•˜λŠ” .kt 의 제일 μœ„μ— 지정(packageκ°€ 있으면 κ·Έ λ‹΄ 쀄에)
 * 6. import ν•΄μ„œ μ‚¬μš©ν•  λ•Œ ν•¨μˆ˜λ“€μ„ 함꼐 μ‚¬μš©ν•  경우, as ν‚€μ›Œλ“œλ‘œ 별칭을 μ§€μ •ν•˜μ—¬ 이름 좩돌이 생기지 μ•Šκ²Œ ν•  수 μžˆλ‹€.
 *
 */

// ν™•μ • 속성 : μ•„λž˜ ν™•μž₯ 속성은 λ¬Έμžμ—΄μ˜ λͺ¨μŒ 개수λ₯Ό μ‚°μΆœν•œλ‹€.
val String.numVowels
    get()= count{"aeiouy".contains(it)}



// String ν΄λž˜μŠ€μ— ν™•μž₯ ν•¨μˆ˜ μΆ”κ°€ν•˜κΈ°
// ν™•μž₯ ν•¨μˆ˜λ₯Ό μ •μ˜ μ‹œμ—, ν™•μž₯ ν•¨μˆ˜ μΆ”κ°€ν•  νƒ€μž…(μˆ˜μ‹ μž νƒ€μž… receiver type)
fun String.addEnthusiasm(amount:Int = 1) = this + "!".repeat(amount)



// Any μ—μ„œ ν™•μž₯ : λͺ¨λ“  νƒ€μž…μ— λŒ€ν•΄ μ‚¬μš©ν•  수 μžˆλ‹€. → easyPrintλŠ” Any의 λͺ¨λ“  μ„œλΈŒνƒ€μž…μ—μ„œ μ‚¬μš©ν•  수 μžˆλ‹€.
// fun Any.easyPrint()  = println(this)
// ↓ 연쇄 호좜 κ°€λŠ₯ ν•˜λ„λ‘ λ³€κ²½ (generic ν™•μž₯ν•¨μˆ˜λ‘œ λ³€κ²½)
// : λ§€κ°œλ³€μˆ˜μΈ Tκ°€ ν™•μž₯ ν•¨μˆ˜μ˜ μˆ˜μ‹ μž νƒ€μž…μœΌλ‘œ μ‚¬μš©λ˜κ³ , Any λŒ€μ‹  T νƒ€μž…μœΌλ‘œ λ°˜ν™˜λ¨.
fun <T> T.easyPrint(): T{
    println(this)
    return this
}


// null κ°€λŠ₯ νƒ€μž…μ— ν™•μž₯ ν•¨μˆ˜ μΆ”κ°€ν•˜κΈ°
// infix : ν•˜λ‚˜μ˜ 인자λ₯Ό κ°–λŠ” ν™•μž₯ ν•¨μˆ˜μ™€ 클래슀 ν•¨μˆ˜ λͺ¨λ‘μ— μ‚¬μš©ν•  수 있으며, ν•¨μˆ˜ 호좜 문법을 κ°„κ²°ν•˜κ²Œ ν•΄μ€Œ.
//         infix ν‚€μ›Œλ“œλ₯Ό μ§€μ •ν•œ 것을 μ€‘μœ„ ν•¨μˆ˜λΌκ³  ν•˜λ©°,
//         μ€‘μœ„ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•ŒλŠ” μˆ˜μ‹ μž 객체와 ν•¨κ»˜ ν•¨μˆ˜ 호좜 μ‚¬μ΄μ˜ 점(.)은 λ¬Όλ‘  이고 인자 μ£Όμœ„μ˜ κ΄„ν˜Έλ„ μƒλž΅ν•  수 μžˆλ‹€.
// μ½”ν‹€λ¦° μ€‘μœ„ ν•¨μˆ˜: shl, shr ushr, and, or , xor, inv
infix fun String?.printWithDefault(default: String) = print(this?: default)



fun main(){
    ("λ§ˆλ“œλ¦¬κ°ˆμ΄ κ·Έ κ±΄λ¬Όμ—μ„œ λ‚˜μ™”μŠ΅λ‹ˆλ‹€.".addEnthusiasm()).easyPrint()
    42.easyPrint()
    // ν•¨μˆ˜ 호좜 μ „κ³Ό ν›„μ—μ„œ easyPrint ν•¨μˆ˜λ₯Ό 각각 ν˜ΈμΆœν•˜κ²Œ λ³€κ²½/ μ•„λž˜λŠ” μ™œ μ—λŸ¬κ°€ λ‚ κΉŒ?
    // > easyPrint 둜 λ°˜ν™˜λœ 값이 Any λΌμ„œ.
    // generic 으둜 λ°”κΎΌ ν›„
    "λ§ˆλ“œλ¦¬κ°ˆ κ·Έ κ±΄λ¬Όμ—μ„œ λ‚˜μ˜΄".easyPrint().addEnthusiasm().easyPrint()

    // ν™•μž₯ 속성 μ‚¬μš©ν•˜κΈ°
    "How many vowels?".numVowels.easyPrint()

    //infix ν‚€μ›Œλ“œ μ“΄ ν™•μž₯ ν•¨μˆ˜ (μ€‘μœ„ ν•¨μˆ˜)
    null printWithDefault "κΈ°λ³Έ λ¬Έμžμ—΄"         // infix ν‚€μ›Œλ“œ μ§€μ •λœ μ€‘μœ„ ν•¨μˆ˜μ—μ„œλ§Œ μ‚¬μš© κ°€λŠ₯
    null.printWithDefault("κΈ°λ³Έ λ¬Έμžμ—΄") // μ€‘μœ„ ν•¨μˆ˜μ™€ 일반 ν•¨μˆ˜ λͺ¨λ‘μ—μ„œ μ‚¬μš© κ°€λŠ₯ν•œ μƒνƒœ


}

//// shuffled.first() 이 ν•¨μˆ˜κ°€ 자주 λ°˜λ³΅λ˜μ—ˆλŠ”λ°, 이런 μ€‘λ³΅λœ μ½”λ“œλŠ” ν™•μž₯ ν•¨μˆ˜λ‘œ μΆ”μΆœ ν•œλ‹€.
//// ↓ 자주 반볡 λ˜λŠ” 것 ν™•μž₯ ν•¨μˆ˜λ‘œ μΆ”μΆœν•˜κΈ°
//// shuffled와 firstλŠ” List와 Set νƒ€μž… λͺ¨λ‘μ— λŒ€ν•΄ 연쇄 호좜됨. λ”°λΌμ„œ 두 νƒ€μž… λͺ¨λ‘μ— ν™•μž₯ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 있게 ν•˜λ €λ©΄
//// 두 νƒ€μž…μ˜ 슈퍼 νƒ€μž…μΈ Iterable을 μˆ˜μ‹ μž νƒ€μž…μœΌλ‘œ μ •μ˜ν•΄μ•Όν•œλ‹€.
//private fun <T> Iterable<T>.random():T = this.shuffled().first()

//// ν™•μž₯ ν•¨μˆ˜ 이름 λ³€κ²½ν•΄μ„œ μ“°κΈ° as
//import mypkg.io.extractKey
//import mypkg.io.extractKey as extracKeyUtil
//
//
//val value1 = extractKey()
//val value2 = extracKeyUtil()

 

null κ°€λŠ₯ νƒ€μž…μ˜ ν™•μž₯ ν•¨μˆ˜. 

 

ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°

https://www.youtube.com/watch?v=6iZDjLvhMN8

 

μ‹œν€€μŠ€ / μ„±λŠ₯ μΈ‘μ •

/**
 * μ‹œν€€μŠ€ : λ‚΄μž₯된 지연(lazy) μ»¬λ ‰μ…˜ νƒ€μž…
 *
 * asSequence ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ Listλ₯Ό μ‹œν€€μŠ€λ‘œ μ‰½κ²Œ λ³€ν™˜ν•  수 μžˆλ‹€.
 *
 * μ„±λŠ₯ μΈ‘μ •
 * - μ½”λ“œ μ„±λŠ₯을 μ•Œλ €μ£ΌλŠ” measureNanoTime , measureTimeInMillis
 * >> 
 * */


fun main() {
    val toList = (1..5000).toList().filter{it.isPrime()}.take(1000)

    // μœ„μ˜ λ‚΄μš©μ„ 지연 μ‹œν€€μŠ€λ₯Ό μ‚¬μš©ν•˜λ©΄
    val oneThousandPrimes = generateSequence(3) {
        value -> value+1
    }.filter { it.isPrime() }.take(1000)
}

// μ†Œμˆ˜μΈμ§€λ₯Ό κ²°μ •ν•˜λŠ” Int νƒ€μž…μ˜ ν™•μž₯ ν•¨μˆ˜
fun Int.isPrime(): Boolean{
    (2 until this).map{
        if(this % it == 0){
            return false
        }
    }
    return true
}


//
λ°˜μ‘ν˜•

λŒ“κΈ€