kotools / types

Explicit types for Kotlin Multiplatform.
https://types.kotools.org
MIT License
90 stars 6 forks source link

✨ New `ClassIdentity` type #643

Open LVMVRQUXL opened 7 months ago

LVMVRQUXL commented 7 months ago

📝 Description

We want to introduce a ClassIdentity experimental type, in the org.kotools.types package of the types Gradle subproject, for representing the identity of a class.

This type should have the following Application Programming Interface (API)

/** Represents a class identity of type [T]. */
interface ClassIdentity<T : Any> {
    /** The name of the class. */
    val name: String

    /** The package containing the class. */
    val packageName: String

    /** Returns the string representation of this class identity. */
    override fun toString(): String

    /** Contains static declarations for the [ClassIdentity] type. */
    companion object {
        /** Creates an instance of [ClassIdentity] for the type [T]. */
        inline fun <reified T : Any> of(): ClassIdentity<T> = TODO()
    }
}

The of factory function being inlined, these declarations should be inaccessible for Java sources.

✅ Checklist

LVMVRQUXL commented 7 months ago

We need more time to think about how can we get the package of a class in a Kotlin Multiplatform project.

LVMVRQUXL commented 7 months ago

A solution is to provide different implementations of this type for each platform.

On the JVM and Native platforms, calling the toString() function should return the qualified name of the corresponding type.

val identity = ClassIdentity.of<Int>()
println(identity) // kotlin.Int

On the JS platform, calling the same function should return the simple name of the corresponding type.

val identity = ClassIdentity.of<Int>()
println(identity) // Int

EDIT on 2024-04-19: This solution is valuable only for serialization, but not for identifying the class in a Java class system. The problem is that, on Kotlin/JS platform, a first.A type and another second.A type would be considered the same regarding this strategy of using the simple name.

A better solution would be to provide the package name to the of factory function, and checking on the Kotlin/JVM and the Kotlin Native platforms that the result of calling the ClassIdentity.toString() function should always return the qualified name of the specified class.

val zeroIdentity: ClassIdentity<Zero> = ClassIdentity.of<Zero>(within = "org.kotools.types")
val actual: String = zeroIdentity.toString()
val expected: String? = Zero::class.qualifiedName
println(actual == expected) // true
LVMVRQUXL commented 7 months ago

The name and the packageName properties shouldn't be exposed as String but as NotBlankString at least.