Type inference for parameterized types in case of cyclic Builder scenario - kotlin

Assuming there exists the following java class:
public class Test {
static class Builder<B extends Builder<B>>{
B asBuilder() {
return (B) this;
}
}
public static <B extends Builder<B>> B newBuilder() {
return new Builder<B>().asBuilder();
}
}
Trying to call Test.newBuilder() in a consuming Kotlin code gives the error Type expected.
Test.newBuilder<>() has the same issue. Test.newBuilder<Test.Builder>() gives the error: One type argument expected for class Builder<B : Test.Builder<B!>!>. Since the type argument is a recursive call this can't be solved in the above fashion.
I believe this is a rather weird behavior even from Java perspective. It's strange that the Test class code was even allowed in its current form. Unfortunately, the above was a simplified version of another class that I have no control of. In reality I am trying to do
org.apache.logging.log4j.core.layout.GelfLayout.newBuilder()

Related

Is it possible to have a field with a generic type that refers to the actual runtime type of the containing class?

I'm fiddling around with this code where I have a base class Node which can be extended:
open class Node
class SubNode : Node()
Now, I have a Behavior class that can be attached to a node, and when this attachment happens, the behavior object is invoked:
open class Behavior {
fun attach(node: Node) {
println("Behavior was attached to a node")
}
}
open class Node {
var behavior: Behavior? = null
set(value) {
field = value
value.attach(this)
}
}
This works, but could this be generified in such way that the type of the attach method would always refer to the actual type of the attached Node? For instance, if the Behavior class was extended like this:
open class Behavior<NodeType: Node> {
open fun attach(node: NodeType) {
}
}
class SubBehavior : Behavior<SubNode>() {
override fun attach(node: SubNode) {
}
}
I've tried various ways of setting up the types in Node class, but can't figure any other way than passing the actual subclass type to the base class (which seems rather cumbersome):
open class Node<SubType: Node> {
var behavior: Behavior<SubType>? = null
}
class SubNode : Node<SubNode>()
Is there a way to do this in any other way?
I think what you need are self types, which don't exist in Kotlin (at least, not yet).
Using recursive generics like you did is the most common way around the problem.
That said, I have trouble understanding your use case here for intertwining these 2 classes together this way. Like how is behaviour used inside your node, etc.

Quarkus/Kotlin: An annotation argument must be a compile-time constant with a java class

In a quarkus/kotlin app, I have a rest client that is very basic:
#Path("/my/api/v1")
#RestClient
interface MyApiClient { }
Problem is, when a request fails, it returns a response that fails to be mapped. So I want to add an exception mapper, in order to log the real error:
class MyExceptionMapper : ResponseExceptionMapper<java.lang.RuntimeException?> {
override fun toThrowable(r: Response): java.lang.RuntimeException {
Logger.getLogger(MyApiClient::class.java).error(r.status)
return RuntimeException("failed")
}
}
To do so, I should annoate my client with:
#RegisterProvider(MyExceptionMapper::class.java)
Doing so, I have a kotlin error:
An annotation argument must be a compile-time constant
I googled but could find solutions only for strings. In this case, kotlin expects the java class to be a compile time constant. How to get it?
Should work with simple:
#RegisterProvider(MyExceptionMapper::class)

Kotlin compiler issue with overriding of Java final function in Kotlin

I’m dealing with following issue with Kotlin/Java Compiler.
Imagine following scenario: let First be a Java class with a final function and Second be a Kotlin class extending First with a function of the same name like the final function in First class, example:
// Java class
class First {
final void foo() { }
}
// Kotlin class
class Second: First() {
fun foo() { }
}
Obviously, it’s wrong because the final function foo() can not be overridden. However, compilation pass successfully and in run-time I get java.lang.LinkageError: Method void Second.foo() overrides final method in class First.
Is this correct behavior of compiler? I supposed that there will be some validations for this case. Thank you!

Mockito mocking method with class parameter vs actual object parameter

What is the difference between these two as per Mockito -
Mockito.when(serviceObject.myMethod(Customer.class)).thenThrow(new
RuntimeException());
and
Customer customer = new Customer();
Mockito.when(serviceObject.myMethod(customer)).thenThrow(new
RuntimeException());
And if both serve the same purpose then using which one is considered to be best practice?
There is a misunderstanding on your side - that method specification myMethod(SomeClass.class) is only possible when the signature of that method allows for a class parameter. Like:
Whatever myMethod(Object o) {
or directly
Whatever myMethod(Class<X> clazz) {
In other words: it is not Mockito that does something special about a parameter that happens to be of class Class!
Thus your first option is not something that works "in general". Example: I put down this code in a unit test:
static class Inner {
public int foo(String s) { return 5; }
}
#Test
public void testInner() {
Inner mocked = mock(Inner.class);
when(mocked.foo(Object.class)).thenReturn(4);
System.out.println(mocked.foo(""));
}
And guess what - the above does not compile. Because foo() doesn't allow for a Class parameter. We can rewrite to
static class Inner {
public int foo(Object o) { return 5; }
}
#Test
public void testInner() {
Inner mocked = mock(Inner.class);
when(mocked.foo(Object.class)).thenReturn(4);
System.out.println(mocked.foo(""));
}
And now the above compiles - but prints 0 (zero) when invoked. Because the above would be the same as mocked.foo(eq(Object.class)). In other words: when your method signature allows for passing a Class instance and you then pass a class instance, that is a simple mocking specification for mockito. In my example: when the incoming object would be Object.class - then 4 would be returned. But the incoming object is "" - therefore the Mockito default kicks in and 0 is returned.
I am with the other answer here - I think you are mixing up that older versions of Mockito asked you to write down when(mocked.foo(any(ExpectedClass.class))) - which can nowadays be written as when(mocked.foo(any())). But when(mocked.foo(ExpectedClass.class)) is not a Mockito construct - it is a simple method specification that gives a specific object to "match on" - and that specific object happens to be an instance of class Class.
First one which uses generic Customer class to match type can also be written as:
Mockito.when(serviceObject.myMethod(Mockito.any(Customer.class))).thenThrow(new
RuntimeException());
In case of the second one, you are passing the actual object that will be used in stubbing.
Usage:
If your method myMethod throws the exception based on the state of the Customer object then you can use the latter approach, where you can set the state of the Customer object appropriately.
However If your method myMethod does not depend on the Customer object to throw the exception rather you need it only to pass it as an argument just to invoke the method, then you can take the former approach.

Kotlin Wildcard Capture on List Callback Parameter

Java:
public class JavaClass implements ModelController.Callback {
#Override
public void onModelsLoaded(#NonNull List<? extends Model> models) {
doSomething(models);
}
private void doSomething(List<Model> models) { }
}
Kotlin:
class ModelController {
var callback = WeakReference<Callback>(null)
interface Callback {
fun onModelsLoaded(models: List<Model>)
}
fun someFunction() {
callback.get().onModelsLoaded(ArrayList<Model>())
}
}
interface Model {
}
Without the ? extends Model in the Java onModelsLoaded method, the override doesn’t match the interface made in Kotlin. With it, I get the following error:
doSomething(<java.util.List<com.yada.Model>) cannot be applied to (java.util.List<capture<? extends com.yada.Model>>)
Why is the wildcard capture required and why doesn't it allow it to be used against the non-wildcard method?
The issue stems from Kotlin collections being variant, and Java only having use-site variance which is implemented though wildcards (capture is something connected to wildcards but not exactly the ? extends ... syntax itself).
When in Kotlin we say List<Model> it means "read-only list of Model or subtypes of Model", when we say the same in Java it means "mutable list of exactly Model and nothing else". To mean roughly what Kotlin's List<Model> means, in Java we have to say List<? extends Model>, this is why for the override to work you have to add the wildcard into the Java code.
Now, your doSomething is written in Java and says that it wants "a list of exactly Model", and when you are giving it "a list of Model or its subtypes", the Java compiler complains, because it can be dangerous: doSomething might try to do something that is not legitimate for a list of, say, ModelImpl, because it thinks it's working on a list of Model.
As of now (Kotlin Beat 2), you have two options:
use MutableList<Model> in your Kotlin code - this mean exactly what Java's List<Model> means, or
define doSomething so that it takes List<? extends Model>, which is what your current Kotlin code means.
In the next update of Kotlin we'll add an annotation on types to facilitate a somewhat cleaner workaround for this problem.
To solve the problem with capture<? extends Model>
You may do something like this:
void doSomething(List<Model> models) {
new ArrayList(models)
}