Skip to content

Instantly share code, notes, and snippets.

@emrul
Forked from avwie/ComponentBag.kt
Created February 26, 2021 23:25
Show Gist options
  • Select an option

  • Save emrul/b25edd2a78a141b031731cbec85c9f50 to your computer and use it in GitHub Desktop.

Select an option

Save emrul/b25edd2a78a141b031731cbec85c9f50 to your computer and use it in GitHub Desktop.

Revisions

  1. @avwie avwie created this gist Feb 26, 2021.
    46 changes: 46 additions & 0 deletions ComponentBag.kt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    package nl.avwie

    interface Tag<T>

    interface Tagged<T> {
    val tag: Tag<T>
    }

    class ComponentBag {
    private val components = mutableMapOf<Tag<*>, Any>()

    fun <T : Tagged<T>> set(component: T) {
    components[component.tag] = component
    }

    @Suppress("UNCHECKED_CAST") // but we are bloody sure the tag is correct
    operator fun <T> get(tag: Tag<T>): T? = components[tag] as? T
    }

    data class Name(val value: String): Tagged<Name> {
    override val tag: Tag<Name> = Name // <- this is the companion object
    companion object : Tag<Name>
    }

    data class Age(val value: Int): Tagged<Age> {
    override val tag: Tag<Age> = Age
    companion object : Tag<Age>
    }

    data class Health(val value: Int): Tagged<Health> {
    override val tag: Tag<Health> = Health
    companion object : Tag<Health>
    }

    fun main() {
    val player = ComponentBag()
    player.set(Name("Beeblebrox"))
    player.set(Age(42))
    player.set(Health(1000))

    // typesafe fetch
    val age = player[Age] // this is automatically if type Age?
    val health = player[Health] // this is automatically of type Health?
    require(age?.value == 42)
    require(health?.value == 1000)
    }