get Not enough information to infer type variable T when initializing kotlin raw types - kotlin

I tried to write raw types for. kotlin in a class and initialized the raw type
class RawType {
interface I<T : RawType?> {
fun f(t: T) {}
}
class RawSubclass: I<T: RawType?> {
override fun f(t: RawType?) {}
}
fun test() {
val unbound = Unbound<T: RawType?>()
}
}
the java I can write
class RawType {
interface I<T extends RawType> {
default void f(T t) {}
}
class BoundRecursively<T extends BoundRecursively<T>> {}
static class RawSubclass implements I {
#Override
public void f(RawType t) {}
}
test() {
Unbound unbound = new Unbound();
}
}
but it gives error Expecting a '>' Expecting member declaration for line class RawSubclass: I<T: RawType?> and Not enough information to infer type variable T for val unbound = Unbound<T: RawType?>(). Any suggestion why the error occurs and how to fix it? Thanks

Related

Kotlin: use generic on interface level as argument type for function

Is it impossible to use generic on interface level as argument type for function?
I read about out and in keywords but as I understand they don't work for this case.
interface BaseB
open class ChildB1: BaseB
open class ChildB2: BaseB
abstract class BaseMapper<V: BaseB> {
open fun test(v: V) {
return
}
}
class TestMapper1: BaseMapper<ChildB1>() {
override fun test(v: ChildB1) {
return
}
}
class TestMapper2: BaseMapper<ChildB2>() {
override fun test(v: ChildB2) {
return
}
}
#Test
fun t() {
//ERROR
val mappers: List<BaseMapper<BaseB>> = listOf(TestMapper1(), TestMapper2())
mappers[0].test(ChildB1())
}
A BaseMapper<ChildB1> is not logically a BaseMapper<BaseB>. It consumes ChildB’s, so if you passed some other implementation of Base it would cause a ClassCastException if the compiler let you do that. There is no common subtype of your two subclasses besides Nothing, so the only way to put both of these types in the same list is to make it a List<BaseMapper<in Nothing>>.
Example of why it is not logically a BaseMapper<BaseB>:
open class ChildB1: BaseB {
fun sayHello() = println("Hello world")
}
class TestMapper1: BaseMapper<ChildB1>() {
override fun test(v: ChildB1) {
v.sayHello() // if v is not a ChildB1, this would be impossible
}
}
//...
val impossibleCast: BaseMapper<BaseB> = TestMapper1()
// TestMapper1 cannot call sayHello() because it's undefined for ChildB2.
// This is impossible:
impossibleCast.test(ChildB2())
// ...so the compiler prevents you from doing the impossible cast in the first place.

Calling an overloaded method with the base class parameter type

Is it possible in Kotlin to call an overloaded method using the base class type as a parameter? This is best illustrated via an example
Base Sealed Class + Derived Classes
sealed class Event {
abstract val eventId: String
}
data class FirstEvent(
override val eventId: String
val first: String
) : Event()
data class SecondEvent(
override val eventId: String
val second: String
) : Event()
Utility Class having an overloaded method for each of the derived classes
class UtilityClass {
fun handle(event: FirstEvent) {
....
}
fun handle(event: SecondEvent) {
....
}
}
Is it possible to call methods of the utility class in such a way utility.handle(FirstEvent("id", "first) as Event) doing so is giving me the following exception
None of the following functions can be called with the arguments supplied.
you can do something like this
fun handleEvent(event: Event) {
when (event) {
is FirstEvent -> {
// event is automatically casted as FirstEvent
event.first
}
is SecondEvent -> ...
}
}

Practical example of sealed classes in Android Development [duplicate]

This question already has answers here:
What are sealed classes in Kotlin?
(3 answers)
Closed 3 years ago.
I'm newbie of Kotlin. I'm learning sealed classes and I don't understand how could I use it in Android development. Can you give me an example?
It's useful when you want to define a closed list of subclasses.
You can use possibility for data classes to extend sealed classes . Example:
fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
// the `else` clause is not required because we've covered all the cases
}
Declaration:
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
Kotlin documentation says:
Sealed classes are used for representing restricted class hierarchies, when a value can have one of the types from a limited set, but cannot have any other type.
Let's take a simple example. You have a sealed abstract class that represents a boolean expression:
sealed class BooleanExpression {
abstract fun evalate(): Boolean
}
Now let's define a class that extends this sealed class:
class OrBooleanExpression(val elem1: Boolean, val elem2: Boolean) : BooleanExpression() {
override fun evalate() = elem1 or elem2
}
Let's now assume for the example that we want a method that prints only the members of a boolean expression. For our or boolean expression, we would have the following:
Elem1 true / Elem2 false
We could implement our method like the following:
fun printMembers(expr: BooleanExpression) = when (expr) {
is OrBooleanExpression -> print("Elem1 ${expr.elem1} / Elem2 ${expr.elem2}")
}
Up to that point, our compiler is happy. Nothing is wrong. In fact, in our when, we have taken into account all subclasses of the sealed class.
Let's add now another boolean expression:
class NotBooleanExpression(val elem1: Boolean) : BooleanExpression() {
override fun evalate(): Boolean = !elem1
}
Now the compiler returns an error:
'when' expression must be exhaustive, add necessary 'is NotBooleanExpression' branch or 'else' branch instead
Now we have two possilities to solve this problem. The first is to add a clause for the new operation:
fun printMembers(expr: BooleanExpression) = when (expr) {
is OrBooleanExpression -> print("Elem1 ${expr.elem1} / Elem2 ${expr.elem2}")
is NotBooleanExpression -> print("Elem1 ${expr.elem1}")
}
Or we could add a else clause:
fun printMembers(expr: BooleanExpression) = when (expr) {
is OrBooleanExpression -> print("Elem1 ${expr.elem1} / Elem2 ${expr.elem2}")
else -> print("Unknown elements")
}
In both case, the compilation works because we have handled all subclasses of the sealed class.
If now we take into account a langage that doesn't have currently sealed class, like Java. We won't be able to do that at compile time. You will therefore need to implement the following using the design pattern Visitor.
interface BooleanExpression {
abstract Boolean evaluate();
abstract <T> T accept(Visitor<T> visitor);
}
class NotBooleanExpression implements BooleanExpression {
private String elem1;
public NotBooleanExpression(String elem1) {
this.elem1 = elem1;
}
public Boolean getElem1() {
return elem1;
}
#Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
class OrBooleanExpression implements BooleanExpression {
private String elem1;
private String elem2;
public NotBooleanExpression(String elem1, String elem2) {
this.elem1 = elem1;
this.elem2 = elem2;
}
public Boolean getElem1() {
return elem1;
}
public Boolean getElem2() {
return elem2;
}
#Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
class Visitor<T> {
T visit(NotBooleanExpression expr);
T visit(OrBooleanExpression expr);
}
class Test {
public void printMembers(expr: BooleanExpression) {
expr.accept(new Visitor<Void>() {
#Override
public Void visit(NotBooleanExpression expr) {
System.out.println("Elem1 " + expr.getElem1());
return null;
}
#Override
public Void visit(OrBooleanExpression expr) {
System.out.println("Elem1 " + expr.getElem1() + " / Elem2" + expr.getElem2());
return null;
}
};
}
}

Custom UiObject2Condition in Kotlin

Is it possible to extend public abstract class UiObject2Condition?
Doing in this way
class NoChildCondition: UiObject2Condition<Boolean>() {
override fun apply(obj: UiObject2?): Boolean {
return obj?.childCount == 0
}
}
causes an error: public open fun apply(obj: UiObject2?): Boolean defined in circlecomplete.ciom.uitests.NoChildCondition' has no access to 'public/*package*/ abstract fun apply(p0: UiObject2!): Boolean! defined in androidx.test.uiautomator.UiObject2Condition', so it cannot override it.
Note that UiObject2Condition is an empty subclass of androidx.test.uiautomator.Condition<UiObject2, R> and Condition is not public.
Implementing apply method causes a compilation error. Not implementing it compiles but causes a runtime error.
UIAutomator version: 2.2.0
UiObject2Condition decompilation:
package androidx.test.uiautomator;
public abstract class UiObject2Condition<R> extends Condition<UiObject2, R> {
public UiObject2Condition() {
}
}
Condition decompilation:
package androidx.test.uiautomator;
abstract class Condition<T, R> {
Condition() {
}
abstract R apply(T var1);
}
Creating androidx.test.uiautomator package and adding class into it works fine.
package androidx.test.uiautomator
class NoChildCondition: UiObject2Condition<Boolean>() {
override fun apply(obj: UiObject2?): Boolean {
return obj?.childCount == 0
}
}

Get companion class in companion object

Is there a way to get the javaClass of the companion class inside a companion object without knowing it's name?
I suppose I could get it by doing something like this:
open class TestClass {
companion object {
init {
val clazz = Class.forName(this::class.java.canonicalName.removeSuffix(".Companion"))
}
}
}
However, this does not work for class InheritingClass : TestClass(). It would still give me TestClass, not InheritingClass.
I was hoping for something more straightforward like this::class.companionClass.
Getting the class of the companion object of a given class will look like this:
TestClass::class.companionObject
Here's an example:
class TestClass {
companion object {
fun sayHello() = "Hello world"
}
}
If you want to get the class that contains the companion, since the latter is always an inner class of the former,
class TestClass {
companion object {
fun whichIsMyParentClass() = this::class.java.declaringClass // It'll return TestClass
}
}
And to further simplify, you'll also want to create an extension property:
import kotlin.reflect.KClass
val <T : Any> KClass<T>.companionClass get() =
if (isCompanion)
this.java.declaringClass
else
null
So, whenever you want to get the parent class of the companion object,
class TestClass {
companion object {
fun whichIsMyParentClass() = this::class.companionClass // It'll return TestClass
}
}
The companion class itself has no reference to the actual class as you can see in this bytecode
public final class TestClass$Companion {
private TestClass$Companion() { // <init> //()V
<localVar:index=0 , name=this , desc=LTestClass$Companion;, sig=null, start=L1, end=L2>
L1 {
aload0 // reference to self
invokespecial java/lang/Object <init>(()V);
return
}
L2 {
}
}
public TestClass$Companion(kotlin.jvm.internal.DefaultConstructorMarker arg0) { // <init> //(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
<localVar:index=0 , name=this , desc=LTestClass$Companion;, sig=null, start=L1, end=L2>
<localVar:index=1 , name=$constructor_marker , desc=Lkotlin/jvm/internal/DefaultConstructorMarker;, sig=null, start=L1, end=L2>
L1 {
aload0 // reference to self
invokespecial TestClass$Companion <init>(()V);
return
}
L2 {
}
}
}
The reference is only the other way around (see decompiled kotlin class)
public final class TestClass {
public static final Companion companion = ...
}
So you can either do it as you just did by cutting off the .Companion part of the class name or you reference it by hard with TestClass::class.java (what is in my opinion no problem and the best solution)
If you need to print the class name, you can add simpleName, such as
this::class.java.declaringClass.simpleName