component-value-clazz
0.1.0indexedOffers a library that enables functional inheritance-based alternatives to value classes, addressing compilation issues across languages and retaining type integrity for public APIs.
Offers a library that enables functional inheritance-based alternatives to value classes, addressing compilation issues across languages and retaining type integrity for public APIs.
A small library that provides a functionally equivalent alternative to Kotlin's
value class via inheritance.
Kotlin's value class is powerful and I use them pervasively, but there are some caveats
to using them.
As a library creator, I've learned that using Kotlin's value class in your public API(s)
(such as kotlin.Result) comes with challenges; I've begun limiting their usage to internal
only.
Ensuring that consumers of your code have a plesant experience, whether they are using Kotlin or not, was the motivation for creating this. Enjoy!
A full list of kotlin-components projects can be found HERE
fun main() {
val id = "123456789"
val userId = UserId(id)
println(userId) // >> UserId(value=123456789)
println(UserId.equals(id)) // >> false
println(id.hashCode()) // >> -1867378635
println(userId.hashCode()) // >> -1867378635
}
class UserId(val id: String): ValueClazz(id)
Usage in sealed classes
fun main() {
println(Data.Loading) // >> Loading
println(Data.UserId("5")) // >> UserId(value=5)
println(Data.UserNames(listOf("matthew", "nelson"))) // >> UserNames(value=[matthew, nelson])
}
(value: Any): ValueClazz(value) {
Loading: Data(NoValue())
( id: String): Data(id)
( names: List<String>): Data(names)
}
Objects objects objects!
fun main() {
println(Objects.Loading.hashCode()) // >> 1859374258
println(Objects.Success.hashCode()) // >> 807752428
println(Objects.Loading.equals(Objects.Success)) // >> false
println(Objects.Loading) // >> Loading
println(Objects.Success) // >> Success
println(Objects.Failure) // >> Failure
}
sealed : (NoValue()) {
Loading: Objects()
Success: Objects()
Failure: Objects()
}
Real world
// build.gradle.kts
dependencies {
// if ValueClazz will be a part of your public API (library devs),
// use api instead of implementation.
implementation("io.matthewnelson.kotlin-components:value-clazz:0.1.0")
}
// build.gradle
dependencies {
// if ValueClazz will be a part of your public API (library devs),
// use api instead of implementation.
implementation "io.matthewnelson.kotlin-components:value-clazz:0.1.0"
}
| value-clazz | kotlin |
|---|---|
| 0.1.0 | 1.8.0 |
This project utilizes git submodules. You will need to initialize them when cloning the repository via:
$ git clone --recursive https://github.com/05nelsonm/component-value-clazz.git
If you've already cloned the repository, run:
$ git checkout master
$ git pull
$ git submodule update --init
In order to keep submodules updated when pulling the latest code, run:
$ git pull --recurse-submodules
value classvalue classvalue class inherits from an interface or sealed interface, it
loses the boxing/unboxing properties that make them so amazing! They become equivalant
to a regular class, with the downside of them not compiling to platform specific
code (as mentioned above).
value classes that implement interfacees, especially if they
are a part of your public API(s), this library is for you!sealed class Address( val value: String): ValueClazz(value) {
abstract fun canonicalHostname(): String
}
sealed class IpAddress(value: String): Address(value)
class IpV4Address
constructor(value: String): IpAddress(value) {
init {
require(value.matches(IPV4_REGEX)) {
"$value is not a valid IPv4 address"
}
}
override fun canonicalHostname(): String = value
}
class IpV6Address
constructor(value: String): IpAddress(value) {
init {
require(value.matches(IPV6_REGEX)) {
"$value is not a valid IPv6 address"
}
}
override fun canonicalHostname(): String = "[$value]"
}
Surfaced from shared tags and platforms — no rankings paid for.