如何正确抽象类型转换函数?
How to abstract type convertion function properly?
我有很多这样的方法:
override suspend fun getBalance(): Result<BigDecimal> = withContext(Dispatchers.IO) {
Log.d(TAG, "Fetching balance from data store")
val balance = balancePreferencesFlow.firstOrNull()
?: return@withContext Result.Error(CacheIsInvalidException)
return@withContext when (balance) {
is Result.Success -> {
if ((balance.data.timestamp + ttl) <= getCurrentTime()) {
deleteBalance()
Result.Error(CacheIsInvalidException)
} else {
resultOf { balance.data.toDomainType() }
}
}
is Result.Error -> balance
}
}
我正在从 DataStore 收集某种类型的流,然后如果它是一个成功结果(具有类型 T 的数据参数),我应该得到它的时间戳(它是一个数据 class 字段) ,如果条件为真,则删除无效数据,如果条件为假,则 return 转换后的结果。
转换函数看起来像这样:
fun BigDecimal.toPersistenceType(): Balance = Balance(
balanceAmount = this,
timestamp = getCurrentTime()
)
fun Balance.toDomainType(): BigDecimal = this.balanceAmount
我试过用这种方式创建一个抽象方法,但我不完全明白我应该如何将 lambda 传递给它。
suspend inline fun <reified T : Any, reified V : Any> getPreferencesDataStoreCache(
preferencesFlow: Flow<Result<V>>,
ttl: Long,
deleteCachedData: () -> Unit,
getTimestamp: () -> Long,
convertData: () -> T
): Result<T> {
val preferencesResult = preferencesFlow.firstOrNull()
return when (preferencesResult) {
is Result.Success -> {
if ((getTimestamp() + ttl) <= getCurrentTime()) {
deleteCachedData()
Result.Error(CacheIsInvalidException)
} else {
resultOf { preferencesResult.data.convertData() }
}
}
is Result.Error -> preferencesResult
else -> Result.Error(CacheIsInvalidException)
}
}
用于转换的 lambda 应该看起来像扩展方法。
结果class:
sealed class Result<out T : Any> {
data class Success<out Type : Any>(val data: Type) : Result<Type>()
data class Error(val exception: Exception) : Result<Nothing>()
}
首先,我在这里看到一些缓存工作,从我的角度来看应该放在一个界面中。
interface Cache {
val timestamp: Long
fun clear()
}
如果您的缓存仍然为空,您可以将 timestamp
属性 设为 null 为 return null
- 这取决于您。
那么你需要的通用方法我假设放在里面 Result
class 因为它似乎只是它自己的工作。
sealed class Result<out T : Any> {
data class Success<out Type : Any>(val data: Type) : Result<Type>()
data class Error(val exception: Exception) : Result<Nothing>()
fun <R : Any> convertIfValid(cache: Cache, ttl: Long, converter: (T) -> R) : Result<R> =
when (this) {
is Success -> {
if (cache.timestamp + ttl <= getCurrentTime()) {
cache.clear()
Error(CacheIsInvalidException())
} else {
Success(converter(data))
}
}
is Error -> this
}
}
也许将 getCurrentTime
方法也放在一些注入的实体中会更好,但这在这个 post 中并不重要。
顺便说一下,正如您在 when
中看到的那样,我没有放置 else
状态,因为密封 classes 不需要它。
根据你的代码,我可以为余额做一个缓存实现的例子:
class BalanceCache : Cache {
var balanceValue = Balance()
override val timestamp: Long
get() = balanceValue.timestamp
override fun clear() {
deleteBalance()
}
}
如果您需要我提供更多示例,请提供有关您的代码的更多详细信息。
我有很多这样的方法:
override suspend fun getBalance(): Result<BigDecimal> = withContext(Dispatchers.IO) {
Log.d(TAG, "Fetching balance from data store")
val balance = balancePreferencesFlow.firstOrNull()
?: return@withContext Result.Error(CacheIsInvalidException)
return@withContext when (balance) {
is Result.Success -> {
if ((balance.data.timestamp + ttl) <= getCurrentTime()) {
deleteBalance()
Result.Error(CacheIsInvalidException)
} else {
resultOf { balance.data.toDomainType() }
}
}
is Result.Error -> balance
}
}
我正在从 DataStore 收集某种类型的流,然后如果它是一个成功结果(具有类型 T 的数据参数),我应该得到它的时间戳(它是一个数据 class 字段) ,如果条件为真,则删除无效数据,如果条件为假,则 return 转换后的结果。
转换函数看起来像这样:
fun BigDecimal.toPersistenceType(): Balance = Balance(
balanceAmount = this,
timestamp = getCurrentTime()
)
fun Balance.toDomainType(): BigDecimal = this.balanceAmount
我试过用这种方式创建一个抽象方法,但我不完全明白我应该如何将 lambda 传递给它。
suspend inline fun <reified T : Any, reified V : Any> getPreferencesDataStoreCache(
preferencesFlow: Flow<Result<V>>,
ttl: Long,
deleteCachedData: () -> Unit,
getTimestamp: () -> Long,
convertData: () -> T
): Result<T> {
val preferencesResult = preferencesFlow.firstOrNull()
return when (preferencesResult) {
is Result.Success -> {
if ((getTimestamp() + ttl) <= getCurrentTime()) {
deleteCachedData()
Result.Error(CacheIsInvalidException)
} else {
resultOf { preferencesResult.data.convertData() }
}
}
is Result.Error -> preferencesResult
else -> Result.Error(CacheIsInvalidException)
}
}
用于转换的 lambda 应该看起来像扩展方法。
结果class:
sealed class Result<out T : Any> {
data class Success<out Type : Any>(val data: Type) : Result<Type>()
data class Error(val exception: Exception) : Result<Nothing>()
}
首先,我在这里看到一些缓存工作,从我的角度来看应该放在一个界面中。
interface Cache {
val timestamp: Long
fun clear()
}
如果您的缓存仍然为空,您可以将 timestamp
属性 设为 null 为 return null
- 这取决于您。
那么你需要的通用方法我假设放在里面 Result
class 因为它似乎只是它自己的工作。
sealed class Result<out T : Any> {
data class Success<out Type : Any>(val data: Type) : Result<Type>()
data class Error(val exception: Exception) : Result<Nothing>()
fun <R : Any> convertIfValid(cache: Cache, ttl: Long, converter: (T) -> R) : Result<R> =
when (this) {
is Success -> {
if (cache.timestamp + ttl <= getCurrentTime()) {
cache.clear()
Error(CacheIsInvalidException())
} else {
Success(converter(data))
}
}
is Error -> this
}
}
也许将 getCurrentTime
方法也放在一些注入的实体中会更好,但这在这个 post 中并不重要。
顺便说一下,正如您在 when
中看到的那样,我没有放置 else
状态,因为密封 classes 不需要它。
根据你的代码,我可以为余额做一个缓存实现的例子:
class BalanceCache : Cache {
var balanceValue = Balance()
override val timestamp: Long
get() = balanceValue.timestamp
override fun clear() {
deleteBalance()
}
}
如果您需要我提供更多示例,请提供有关您的代码的更多详细信息。