Switch between activities but global function - kotlin

I want to create a global function and I want to switch between activities with this function.
Extensions.kt
fun goActivity(context: Context, goClass: Class<Any>) {
val homeIntent = Intent(context, goClass)
homeIntent.flags =
Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
context.startActivity(homeIntent)
(context as Activity).finish()
}
anyActivity
goActivity(context,HomeActivity::class.java)
erromessage
Type mismatch: inferred type is Class but Class was expected

Related

Class constructor asks for 'customPredicate: Message.() -> Boolean' and I cant figure out what is it mean

I have an the following Interface
interface Filter {
fun checkFor(message: Message): Boolean = message.predicate()
fun Message.predicate(): Boolean
infix fun and(otherFilter: Filter): Filter = object : Filter {
override fun Message.predicate(): Boolean =
this#Filter.checkFor(this) && otherFilter.checkFor(this)
}
infix fun or(otherFilter: Filter): Filter = object : Filter {
override fun Message.predicate(): Boolean =
this#Filter.checkFor(this) || otherFilter.checkFor(this)
}
operator fun not(): Filter = object : Filter {
override fun Message.predicate(): Boolean = !this#Filter.checkFor(this)
}
class Custom(private val customPredicate: Message.() -> Boolean) : Filter {
override fun Message.predicate(): Boolean = customPredicate()
}
object All : Filter {
override fun Message.predicate(): Boolean = true
}
In this Interface I have a class named "Custom"
which ask in the constructor for
class Custom(private val customPredicate: Message.() -> Boolean)
And I have no idea how should I use this class to create my own Filter
Please assist
There are quite a few ways you can create an object of Custom class.
You can use the lambda expression as a function with the receiver, the receiver is available inside the body as context.
val custom = Custom { //lambda begins here
//here you can call any method of Message, which is the receiver
}
You can create an extension function of Message and pass its reference to the Custom class constructor.
fun Message.customPredicate() {
// Your code here
}
Pass reference of this function to the constructor of the Custom class
val custom = Custom(Message::customPredicate)
You can also use an anonymous function for creating an object of the Custom class.
val custom = Custom(fun Message.() {
// Your code here
})

How to define an object for function to return

I am trying this snippet from Hyperskill in Kotlin.
I have tried in an IDE but keep getting error because of inproper Product reference.
How can I create a proper Product object to make it run?
class Fridge {
fun open() = println(1)
fun find(productName: String): Product {
println(productName)
return 4
}
fun close() = println(3)
}
The issue here is that you are trying to return integer (return 4) from method find(String): Product, but you are declaring return type of Product.
You gave to either return object of a class Product or change the method to return Int (fun find(productName: String): Int).
In order to return an object of class Product, the following code is sufficient:
class Product
class Fridge {
fun open() = println(1)
fun find(productName: String): Product {
println(productName)
return Product()
}
fun close() = println(3)
}

Kotlin Lambda with generic input parameter gets inferred to Nothing when stored in a collection

I have the following classes
class EventHandler<A : Aggregate, E : Event<A>>(
val eventClazz: KClass<out Event<A>>,
val handle: suspend (E) -> Unit
)
class Projection(vararg handlers: EventHandler<out Aggregate, out Event<out Aggregate>>) {
val handlers = handlers.asList()
}
Now I want to invoke the handlers handle function. The Handler is stored in a Projections handlers list.
val subscriptionFilterBuilder = SubscriptionFilterBuilder()
projections.forEach { projection ->
projection.handlers.forEach { handler: EventHandler<out Aggregate, out Event<out Aggregate>> ->
val eventType = getEventType(handler.eventClazz)
val filter = subscriptionFilterBuilder.withEventTypePrefix(eventType).build()
val options = SubscribeToAllOptions.get().filter(filter)
val handlerTarget: KClass<out Event<out Aggregate>> = handler.eventClazz
coroutineScope.launch {
eskWrapper.subscribeToAll(
options = options,
) { subscription, event ->
val deserialized: Event<out Aggregate> =
serDes.deserialize2(event.originalEvent).eventPayload
coroutineScope.launch {
handler.handle(deserialized)
}
}
}
}
}
The compiler gives me the error Type mismatch: inferred type is Event<out Aggregate> but Nothing was expected for the line handler.handle(deserialized).
I guess this is because of the way I store the handlers in the Projection but I don't know how to solve this.
I found a way to ensure type safety in my case.
I can add a function to the EventHandler which takes care of deserialization and invoking the actual handling function. Since this handleWithSer function (don't use this name) is aware of the generic types this approach works.
class EventHandler<A : Aggregate, E : Event<A>>(
val eventClazz: KClass<out Event<A>>,
val handle: suspend (E) -> Unit,
) {
val handleWithSer: suspend (RecordedEvent, EventPayloadSerDes) -> Unit =
{ event: RecordedEvent, serder: EventPayloadSerDes ->
val event = serder.deserialize<A, E>(event)
handle(event.eventPayload)
}
}
If there are other ways to get the correct type from the collection let me know.

Kotlin - TypeReference<T> Cannot obtain Class<*> For Type Arguments

I've created a Kotlin equivalent of TypeReference<T> like so:
abstract class TypeReference<T> : Comparable<T> {
val type: Type get() = getGenericType()
val arguments: List<Type> get() = getTypeArguments()
final override fun compareTo(other: T): Int {
return 0
}
private fun getGenericType(): Type {
val superClass = javaClass.genericSuperclass
check(superClass !is Class<*>) {
"TypeReference constructed without actual type information."
}
return (superClass as ParameterizedType).actualTypeArguments[0]
}
private fun getTypeArguments(): List<Type> {
val type = getGenericType()
return if (type is ParameterizedType) {
type.actualTypeArguments.toList()
} else emptyList()
}
}
In order to obtain Class<*> of the generic type and its arguments, I've also created the following extension function (and this is where I believe the problem lies, since this is where the stack trace fails).
fun Type.toClass(): Class<*> = when (this) {
is ParameterizedType -> rawType.toClass()
is Class<*> -> this
else -> Class.forName(typeName)
}
I'm unit testing this like so:
#Test
fun `TypeReference should correctly identify the List of BigDecimal type`() {
// Arrange
val expected = List::class.java
val expectedParameter1 = BigDecimal::class.java
val typeReference = object : TypeReference<List<BigDecimal>>() {}
// Act
val actual = typeReference.type.toClass()
val actualParameter1 = typeReference.arguments[0].toClass()
// Assert
assertEquals(expected, actual)
assertEquals(expectedParameter1, actualParameter1)
}
The problem I think, lies in the extension function else -> Class.forName(typeName) as it throws:
java.lang.ClassNotFoundException: ? extends java.math.BigDecimal
Is there a better way to obtain the Class<*> of a Type, even when they're generic type parameters?
You need to add is WildcardType -> ... branch to your when-expression to handle types like ? extends java.math.BigDecimal (Kotlin equivalent is out java.math.BigDecimal), ?(Kotlin equivalent is *), ? super Integer(Kotlin equivalent is in java.math.Integer):
fun Type.toClass(): Class<*> = when (this) {
is ParameterizedType -> rawType.toClass()
is Class<*> -> this
is WildcardType -> upperBounds.singleOrNull()?.toClass() ?: Any::class.java
else -> Class.forName(typeName)
}
Note that in this implementation single upper bound types will be resolved as its upper bound, but all other wildcard types (including multiple upper bounds types) will be resolved as Class<Object>
https://github.com/pluses/ktypes
val typeReference = object : TypeReference<List<BigDecimal>>() {}
val superType = typeReference::class.createType().findSuperType(TypeReference::class)!!
println(superType.arguments.first())// List<java.math.BigDecimal>
println(superType.arguments.first().type?.arguments?.first())// java.math.BigDecimal

How to use reduce function correctly with functional programming in kotlin

I am trying to pass a function and want to use reduce on it.
This is the data class
data class TestClass(
var variable1: BigDecimal?,
var variable2: BigDecimal?
)
This is the function which I want to work
fun aggregateAll() {
helperfunc(TestClass::variable1::get,someDummmyFilledListOfTestClass)
}
fun helperfunc(function: () ->BigDecimal, testList:List<TestClass>) {
var aggregatedValue:BigDecimal = BigDecimal.ZERO
testList.map{function}.reduce{aggregatedValue,element -> aggregatedValue.add(element)}
}
fun main() {
val someDummmyFilledListOfTestClass = listOf<TestClass>(
TestClass(1.toBigDecimal()),
TestClass(199.toBigDecimal()),
TestClass(null),
TestClass(501.toBigDecimal())
)
val result = helperfunc(someDummmyFilledListOfTestClass, TestClass::variable1::get)
// trailing lambda
// or val result = helperfunc(someDummmyFilledListOfTestClass) { it.variable1 }
println(result)
}
/* lambda last parameter for trailing lambda */
fun helperfunc(testList: List<TestClass>, function: (TestClass) -> BigDecimal?): BigDecimal {
return testList
// map TestClass to BigDecimal? and filter nulls
.mapNotNull(function)
// fold with initial value, reduce will throw exception if list is empty
.fold(BigDecimal.ZERO) { acc, element -> acc.add(element) }
}
data class TestClass(
var variable1: BigDecimal?
// var variable2: BigDecimal?
)
For the map function to work, your function type needs a TestClass parameter, so it should be (TestClass) -> BigDecimal.
And your variable1 needs to be non-nullable, or it else its getter is a (TestClass) -> BigDecimal?, which doesn't match the required type.
And when you pass the function to map, don't wrap it in a lambda, because then you are just creating a function that returns your other function.
And you seem to want to use a separate aggregator rather than the first element of the list, so that means you should use fold instead of reduce.
data class TestClass(
var variable1: BigDecimal,
var variable2: BigDecimal?
)
fun aggregateAll() {
helperfunc(TestClass::variable1::get, someDummmyFilledListOfTestClass)
}
fun helperfunc(function: (TestClass) -> BigDecimal, testList:List<TestClass>) {
val sum: List<BigDecimal> =
testList.map(function).fold(BigDecimal.ZERO) { aggregatedValue, element -> aggregatedValue.add(element)}
}