Last active
July 11, 2024 05:58
-
-
Save kittinunf/e5fc92f6ae475f5d413dded926ecfdfa to your computer and use it in GitHub Desktop.
Kotlin2.0 and Beyond
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.github.kittinunf.kotlin2_0 | |
import kotlinx.coroutines.flow.Flow | |
import kotlinx.coroutines.flow.MutableSharedFlow | |
fun example1() { | |
// 1. | |
/** | |
* 1. Better operator and understanding code | |
* | |
*/ | |
data class Foo(val mutableList: MutableList<Long> = mutableListOf(1, 2)) | |
val f = Foo() | |
f.mutableList[0] += 1 | |
var i: Long = 0 | |
i += 1 | |
// -- | |
println(f.mutableList) | |
} | |
fun example2() { | |
// 2. | |
/** | |
* 2. Smart-casts from variables, this goes beyond the scope | |
* | |
*/ | |
class Cat { | |
fun meow() { | |
println("Meow meow") | |
} | |
} | |
fun pet(animal: Any) { | |
if (animal is Cat) { | |
animal.meow() | |
} | |
val anotherCat = animal is Cat | |
if (anotherCat) { | |
anotherCat.meow() | |
} | |
} | |
//-- | |
data class Card(val value: String?) | |
fun getCardValue(card: Any): String { | |
val cardWithValue = card is Card && card.value.isNullOrEmpty().not() | |
return when { | |
cardWithValue -> { | |
card.value | |
} | |
else -> "no value" | |
} | |
} | |
println(getCardValue(Card("value"))) | |
// -- | |
fun workWithStatus(status: Any) { | |
if (status is HttpStatus.OK || status is HttpStatus.Error) { | |
println(status.message()) | |
} | |
} | |
} | |
sealed interface HttpStatus { | |
fun message(): String | |
interface OK : HttpStatus | |
interface Error : HttpStatus | |
interface Custom : HttpStatus | |
} | |
fun example3() { | |
// 3. | |
/** | |
* 3. Data flow and guarded condition | |
* | |
*/ | |
fun getType(): Data.Type { | |
error("....") | |
} | |
fun doSomethingWithSearchData( | |
data: Sequence<Data>, | |
id: String | |
) { | |
val lastData = data.last { it.id == id } | |
when (val type = getType()) { | |
Data.Type.A if type.allow | |
-> { | |
// Do something with A and if it is allowed only | |
} | |
Data.Type.B -> {} | |
Data.Type.C -> {} | |
} | |
} | |
fun doSomethingBetterWithSearchData( | |
data: Sequence<Data>, | |
id: String | |
) { | |
val lastData = data.last { it.id == id } | |
when (val type = getType()) { | |
is A if type.allowed | |
-> { | |
// Do something with A and if it is allowed only | |
} | |
B -> {} | |
C -> {} | |
} | |
} | |
} | |
interface Data { | |
enum class Type { | |
A { | |
val allowed: Boolean = true | |
}, | |
B { | |
}, | |
C { | |
} | |
; | |
} | |
val id: String | |
} | |
fun example4() { | |
// 4. | |
/** | |
* 4. ADT Style smart casts | |
* | |
*/ | |
fun <T> unwrapped(container: Container<T>): T = container.inner | |
fun <T> unwrappedAndDoSomething(container: Container<T>): T = when (container) { | |
is IntegerContainer -> container.inner | |
is StringContainer -> container.inner | |
} | |
} | |
sealed class Container<T>(val inner: T) | |
class IntegerContainer : Container<Int>(42) | |
class StringContainer : Container<String>("Kotlin") | |
fun example5() { | |
// 5. | |
/** | |
* 5. Data classes improvement | |
* | |
*/ | |
data class User(val name: String, val surname: String) | |
fun doSomething(u: User) { | |
val (surname, name) = u | |
} | |
} | |
fun example6() { | |
// 6. | |
/** | |
* 6. Dataargs | |
* | |
*/ | |
fun LazyColumn( | |
modifier: Modifier = Modifier, | |
state: LazyListState = rememberLazyListState(), | |
contentPadding: PaddingValues = PaddingValues(0), | |
reverseLayout: Boolean = false, | |
verticalArrangement: Arrangement.Vertical = | |
if (reverseLayout) Arrangement.Top else Arrangement.Bottom, | |
horizontalAlignment: Alignment.Horizontal = Alignment.Start, | |
userScrollEnabled: Boolean = true, | |
flingBehavior: FlingBehavior, | |
content: LazyListScope.() -> Unit | |
) { | |
// Implementation | |
} | |
dataarg class ColumnSettings( | |
val contentPadding: PaddingValues = PaddingValues(0), | |
val reverseLayout: Boolean = false, | |
val verticalArrangement: Arrangement.Vertical = | |
if (reverseLayout) Arrangement.Top else Arrangement.Bottom, | |
val horizontalAlignment: Alignment.Horizontal = Alignment.Start, | |
val userScrollEnabled: Boolean = true, | |
) | |
fun LazyColumn( | |
modifier: Modifier = Modifier, | |
state: LazyListState = rememberLazyListState(), | |
dataarg args: ColumnSettings, | |
flingBehavior: FlingBehavior, | |
content: LazyListScope.() -> Unit | |
) { | |
// Implementation | |
} | |
LazyColumn(reverseLayout = true) { | |
} | |
} | |
object Modifier | |
interface LazyListState | |
fun rememberLazyListState(): LazyListState {} | |
interface PaddingValues | |
fun PaddingValues(i: Int): PaddingValues {} | |
interface Arrangement { | |
object Top : Arrangement.Vertical | |
object Bottom : Arrangement.Vertical | |
interface Vertical : Arrangement | |
} | |
interface Alignment { | |
object Start : Horizontal | |
interface Horizontal : Alignment | |
} | |
interface FlingBehavior | |
interface LazyListScope | |
fun example7() { | |
// 7. | |
/** | |
* 7. Built-in Error Abstract type | |
* | |
*/ | |
fun <T> Sequence<T>.last(predicate: (T) -> Boolean): T? { | |
var result: T? = null | |
for (element in this) { | |
if (predicate(element)) result = element | |
} | |
return result ?: throw NoSuchElementException() | |
} | |
// right?? | |
// now with { it == null } | |
fun <T> Sequence<T>.lastImproved(predicate: (T) -> Boolean): T? { | |
var result: T? = null | |
var found: Boolean = false | |
for (element in this) { | |
if (predicate(element)) { | |
result = element | |
found = true | |
} | |
} | |
if (!found) throw NoSuchElementException() | |
return result as T | |
} | |
fun <T> Sequence<T>.lastImprovedFinal(predicate: (T) -> Boolean): T? { | |
var result: Any? = NotFound | |
for (element in this) { | |
if (predicate(element)) { | |
result = element | |
} | |
} | |
if (result == NotFound) throw NoSuchElementException() | |
return result as T | |
} | |
sealed class Value { | |
data class Success(value: String) : Value | |
object Failure : Value | |
} | |
fun <T> Sequence<T>.lastImprovedFinalFinal(predicate: (T) -> Boolean): T? { | |
var result: (T | NotFound) = NotFound | |
for (element in this) { | |
if (predicate(element)) { | |
result = element | |
} | |
} | |
if (result == NotFound) throw NoSuchElementException() | |
return result | |
} | |
} | |
private object NotFound | |
interface Value | |
fun example8() { | |
// 8. | |
/** | |
* 8. Explicit backing fields | |
* | |
*/ | |
class Repository() { | |
private val _values = MutableSharedFlow<Value>() | |
val values: Flow<Value> get() = _values | |
} { | |
fun something() { | |
_values.emit(t) = .... | |
} | |
} | |
val r = Repository() | |
r.values.collect { | |
} | |
class RepositoryImproved() { | |
val values: Flow<Value> | |
field = MutableSharedFlow<Value> | |
} | |
} | |
fun main() { | |
example1() | |
example2() | |
example3() | |
example4() | |
example5() | |
example6() | |
example7() | |
example8() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment