0Pricing
Kotlin Academy · Lekcja

Wymazywanie typów i parametry typów reified

Używaj reified z funkcjami inline, aby uzyskiwać informacje o typach w czasie działania.

Wymazywanie typów i parametry typów reified to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Czym jest wymazywanie typów?

W czasie działania JVM wymazuje argumenty typów generycznych. List<String> i List<Int> są wtedy po prostu obiektami typu List. Ogranicza to operacje na typach generycznych dostępne w czasie działania.

fun main() {
    val strings: List<String> = listOf("a", "b")
    val ints: List<Int> = listOf(1, 2)
    println(strings.javaClass == ints.javaClass) // true: both ArrayList
    println(strings is List<*>)  // OK with star
    // println(strings is List<String>) // warning: unchecked cast
}

Problem: nie można sprawdzać wymazanych typów

Nie można używać is z konkretnym argumentem typu generycznego, ponieważ informacje o typie znikają w czasie działania.

fun checkType(obj: Any) {
    // This works:
    if (obj is List<*>) println("It's a list of something")
    // This doesn't compile cleanly:
    // if (obj is List<String>) println("It's a list of strings") // unchecked
}
fun main() {
    checkType(listOf("hello"))
    checkType(42)
}

Podsumowanie funkcji inline

inline kopiuje treść funkcji do miejsca wywołania podczas kompilacji. To właśnie umożliwia użycie reified — argument typu również jest podstawiany w miejscu wywołania.

inline fun <T> myRun(block: () -> T): T = block()
fun main() {
    val result = myRun { 42 }
    println(result) // 42
    // The compiler inlines the lambda body — no object allocation
}

reified: dostęp do T w czasie działania

Połączenie inline z reified zachowuje argument typu w miejscu wywołania, umożliwiając użycie is, as i ::class dla T.

inline fun <reified T> isInstance(value: Any): Boolean = value is T
fun main() {
    println(isInstance<String>("hello"))  // true
    println(isInstance<Int>("hello"))     // false
    println(isInstance<List<*>>(listOf())) // true
}

Pobieranie KClass typu T

Dzięki reified T można uzyskać T::class w czasie działania — co normalnie jest niemożliwe w funkcjach generycznych.

inline fun <reified T> classNameOf(): String = T::class.simpleName ?: "Unknown"
fun main() {
    println(classNameOf<String>())   // String
    println(classNameOf<Int>())      // Int
    println(classNameOf<List<*>>())  // List
}

Bezpieczne rzutowanie z reified

Użyj reified, aby napisać bezpieczną typowo funkcję pomocniczą do rzutowania, która zamiast zgłaszać wyjątek zwraca null.

inline fun <reified T> Any?.safeCast(): T? = this as? T
fun main() {
    val obj: Any = "Hello"
    val s: String? = obj.safeCast<String>()
    val i: Int? = obj.safeCast<Int>()
    println(s) // Hello
    println(i) // null
}

Analizowanie JSON z reified

Biblioteki takie jak Gson lub kotlinx.serialization używają reified do wywnioskowania typu docelowego w miejscu wywołania bez jawnego przekazywania obiektów Class.

import com.google.gson.Gson
// Simulated without real Gson:
inline fun <reified T> parseJson(json: String): T {
    return Gson().fromJson(json, T::class.java)
}
// Usage:
// val user: User = parseJson<User>("""{"name":"Alice"}""")

reified z filterIsInstance

Funkcja filterIsInstance<T>() z biblioteki standardowej używa reified do filtrowania listy do określonego typu bez ręcznego rzutowania.

fun main() {
    val mixed: List<Any> = listOf(1, "hello", 2.5, "world", true)
    val strings = mixed.filterIsInstance<String>()
    val ints = mixed.filterIsInstance<Int>()
    println(strings) // [hello, world]
    println(ints)    // [1]
}

Nie można używać reified w funkcjach innych niż inline

reified działa tylko z funkcjami inline. Próba użycia go bez inline powoduje błąd kompilacji.

// Error:
// fun <reified T> broken(): String = T::class.simpleName ?: "?"

// Must be inline:
inline fun <reified T> correct(): String = T::class.simpleName ?: "?"
fun main() {
    println(correct<Double>()) // Double
}

reified i refleksja

Połącz reified z refleksją, aby dynamicznie sprawdzać właściwości lub adnotacje typu bez powtarzalnych parametrów Class.

inline fun <reified T : Any> properties(): List<String> =
    T::class.members.map { it.name }
data class Point(val x: Int, val y: Int)
fun main() {
    println(properties<Point>()) // [x, y, component1, component2, copy, equals, hashCode, toString]
}

Praktyka: bezpieczny typowo lokalizator usług

Użyj reified do zbudowania lokalizatora usług, który mapuje KClass na instancje, zapewniając lekkie DI bez procesorów adnotacji.

val registry = mutableMapOf<kotlin.reflect.KClass<*>, Any>()
inline fun <reified T : Any> register(instance: T) { registry[T::class] = instance }
@Suppress("UNCHECKED_CAST")
inline fun <reified T : Any> resolve(): T = registry[T::class] as T
class Logger { fun log(msg: String) = println("[LOG] $msg") }
fun main() {
    register(Logger())
    resolve<Logger>().log("Service located!")
}

Ograniczenia reified

Parametrów typu reified nie można używać w kontekstach innych niż inline, nie można przechowywać typu do późniejszego użycia ani przekazywać ich do funkcji innych niż inline, które potrzebują typu w czasie działania.

inline fun <reified T> foo() {
    val clazz = T::class // OK here
    // bar(clazz)        // must pass clazz explicitly to non-inline funs
    println(clazz.simpleName)
}
fun bar(clazz: kotlin.reflect.KClass<*>) = println(clazz.simpleName)
fun main() { foo<String>() }

Szybkie sprawdzenie

Co jest wymagane, aby parametr typu był reified?

Podsumowanie

Wymazywanie typów usuwa informacje o typach generycznych w czasie działania. reified w funkcjach inline zachowuje argument typu w miejscu wywołania, umożliwiając użycie is, as, ::class i refleksji dla T — bez ręcznego przekazywania obiektów Class.

Często zadawane pytania

Czy lekcja „Wymazywanie typów i parametry typów reified” jest bezpłatna?

Tak — pełny tekst „Wymazywanie typów i parametry typów reified” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wymazywanie typów i parametry typów reified”?

Używaj reified z funkcjami inline, aby uzyskiwać informacje o typach w czasie działania. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Wymazywanie typów i parametry typów reified”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Funkcje generyczne i ograniczenia typów za pomocą where
  2. Wariancja deklarowana w miejscu deklaracji: in i out
  3. Projekcja gwiazdkowa i kiedy używać *
  4. Wymazywanie typów i parametry typów reified
← Powrót do Kotlin Academy