Convert Java to Kotlin (With a function as an argument) - kotlin

I want this code in Kotlin:
public class LobbySwitcherGui extends AGUI
{
public LobbySwitcherGui()
{
super(27, "someTitle");
setItem(0, new ItemStack(Material.NETHER_STAR), player -> {
player.sendMessage("Some message");
});
}
}
but if I convert it in IntellIJ its doesnt work for me.
class LobbySwitcherGui : AGUI(27, "someTitle")
{
init {
setItem(0, ItemStack(Material.NETHER_STAR), { player -> player.sendMessage("Some message") })
}
}
The last Argument istn working and I cant fix it..
AGUI class is this: https://ghostbin.com/paste/gjdzo

kotlin can create Runnables and Function, BiFunction, etc that way..
you seem to create something called a YourGUIAction, check if that might be replaced with action: (Player) -> Unit
or in general (ArgumentTypes) -> ReturnType

Related

Mockito: How to mock lambda callback? what is the type? (Kotlin)

I have two class TestTarget, MockTarget and test code below. If the TestTarget has two functions with same name and same count of parameter, the any() is ambiguous. I need to assign the type to any(ClassType). But what is the type of () -> Unit? I have tried Function0 and it doesn't work. Can anyone help?
Class TestTarget:
Class TestTarget(private val mockTarget: MockTarget) {
fun testFunction() {
// some logic to be tested.
// call mockTarget.doSomething.
}
}
Class MockTarget
Class MockTarget {
fun doSomething(callback: () -> Unit) {
// some logic here.
}
fun doSomething(listener: OtherType) {
// Test code works without this function.
}
}
Test Code:
// setup mocks.
#Test
fun `verify testFunction`() {
`when`(mockTarget.doSomething(any())).thenAnswer { invocation ->
// callback here.
}
}
Replace org.mockito.Mockito with org.mockito.kotlin.*
and you can code like this
val anyLambda = any<() -> Unit>()
val anyListener = any<OtherType>()

Kotlin - Trying to factorize code with high-order function

I'm quite new to Kotlin and I'd like to see if using high-order functions can help in my case.
My use-case is that I need to call the methods of an IInterface derived class to send events to one or more components. And I'd like to make this generic, and I want to check if a high-order funtion can help. A sample of code will help to understand (well, I hope so!).
private val eventListeners = mutableListOf<IEventInterface>() // List filled somewhere else!
private fun sendConnectionEvent(dummyString: String) {
val deadListeners = mutableListOf<IEventInterface>()
eventListeners.forEach {
try {
it.onConnectionEvent(dummyString)
} catch (e: DeadObjectException) {
Log.d(TAG, "Removing listener - Exception ${e.message}")
deadListeners.add(it)
}
}
deadListeners.forEach { it ->
eventListeners.remove(it)
}
}
private fun sendWonderfulEvent(dummyString: String, dummyInt: Int) {
val deadListeners = mutableListOf<IEventInterface>()
eventListeners.forEach {
try {
it.onWonderfulEvent(dummyString, dummyInt)
} catch (e: DeadObjectException) {
Log.d(TAG, "Removing listener - Exception ${e.message}")
deadListeners.add(it)
}
}
deadListeners.forEach { it ->
eventListeners.remove(it)
}
}
I added 2 similar methods (I will have many more in the real use case) and I think (I hope!) that something could be done but I can't make high-order function works in this case because:
I want to call the same method on several instances, and not 'just' a basic function
To make things even worse, the methods I need to call don't have the same prototype (that would have been too easy!).
Hope this is clear enough.
Thanks for your help!
VR
Here is how it can be done
fun onEvent(body: (IEventInterface) -> Unit) {
val deadListeners = mutableListOf<IEventInterface>()
eventListeners.forEach {
try {
body(it)
} catch (ex: DeadObjectException) {
Log.d(TAG, "Removing listener - Exception ${e.message}")
deadListeners.add(it)
}
}
deadListeners.forEach { it ->
eventListeners.remove(it)
}
}
Supposing an interface like this:
interface IEventInterface {
fun onConnectionEvent(dummyString: String)
fun onWonderfulEvent(dummyString: String, dummyInt: Int)
}
Define an generic type that implements your defined interface ( <T : IEventInterface>)
Define an mutable list of this type to receive your implementation (MutableList<T>.removeIfThrows)
Expect an extension function for you type that will do your specific validation (and custom parameters if you want)
Using an apply and returning the instance you can run your code like a pipeline
Executing the custom validation when you want
private fun <T : IEventInterface> MutableList<T>.removeIfThrows(validation: T.() -> Unit, customLogMessage: String? = null): MutableList<T> {
return apply {
removeIf {
it.runCatching {
validation()
}.onFailure { error ->
print(customLogMessage ?: "Removing listener - Exception ${error.message}")
}.isFailure
}
}
}
Define your specific implementation passing just the function with custom validation as an parameter
private fun <T : IEventInterface> MutableList<T>.sendConnectionEvent(dummyString: String) = removeIfThrows({
onConnectionEvent(dummyString)
})
private fun <T : IEventInterface> MutableList<T>.sendWonderfulEvent(dummyString: String, dummyInt: Int) = removeIfThrows({
onWonderfulEvent(dummyString, dummyInt)
})
Now you can run your code like an pipeline modifying your original object like this
private fun nowYouCanDoSomethingLikeThis() {
eventListeners
.sendConnectionEvent("some dummy string")
.sendWonderfulEvent("some another dummy string", 123)
}

Extension functions issue

Run into some difficulties while using extension functions with existing java api. Here some pseudocode
public class Test {
public Test call() {
return this;
}
public Test call(Object param) {
return this;
}
public void configure1() {
}
public void configure2(boolean value) {
}
}
Kotlin test
fun Test.call(toApply: Test.() -> Unit): Test {
return call()
.apply(toApply)
}
fun Test.call(param: Any, toApply: Test.() -> Unit): Test {
return call(param)
.apply(toApply)
}
fun main(args: Array<String>) {
val test = Test()
//refers to java method; Unresolved reference: configure1;Unresolved reference: configure2
test.call {
configure1()
configure2(true)
}
//refers to my extension function and works fine
test.call(test) {
configure1()
configure2(true)
}
}
Why only function with param works fine ? what’s the difference ?
Kotlin will always give precedence to the classes member functions. Since Test:call(Object) is a possible match, Kotlin selects that method rather than your extension function.
The extension function with the added parameter is resolved the way you expect because the Test class does not have any member functions that would take precedent (no matching signature), so your extension method is selected.
Here is a link to the Kotlin documentation as to how extension functions are resolved: https://kotlinlang.org/docs/reference/extensions.html#extensions-are-resolved-statically

Method References to Super Class Method

How to use method references to refer to super class methods?
In Java 8 you can do SubClass.super::method.
What would be the syntax in Kotlin?
Looking forward to your response!
Conclusion
Thanks to Bernard Rocha!
The syntax is SubClass::method.
But be careful. In my case the subclass was a generic class. Don't forget to declare it as those:
MySubMap<K, V>::method.
EDIT
It still doesn't work in Kotlin.
Hers's an example in Java 8 of a method reference to a super class method:
public abstract class SuperClass {
void method() {
System.out.println("superclass method()");
}
}
public class SubClass extends SuperClass {
#Override
void method() {
Runnable superMethodL = () -> super.method();
Runnable superMethodMR = SubClass.super::method;
}
}
I'm still not able to do the same in Kotlin...
EDIT
This is an example how I tried to achieve it in Kotlin:
open class Bar {
open fun getString(): String = "Hello"
}
class Foo : Bar() {
fun testFunction(action: () -> String): String = action()
override fun getString(): String {
//this will throw an StackOverflow error, since it will continuously call 'Foo.getString()'
return testFunction(this::getString)
}
}
I want to have something like that:
...
override fun getString(): String {
//this should call 'Bar.getString' only once. No StackOverflow error should happen.
return testFunction(super::getString)
}
...
Conclusion
It's not possible to do so in Kotlin yet.
I submitted a feature report. It can be found here: KT-21103 Method Reference to Super Class Method
As the documentation says you use it like in java:
If we need to use a member of a class, or an extension function, it
needs to be qualified. e.g. String::toCharArray gives us an extension
function for type String: String.() -> CharArray.
EDIT
I think you can achieve what you want doing something like this:
open class SuperClass {
companion object {
fun getMyString(): String {
return "Hello"
}
}
}
class SubClass : SuperClass() {
fun getMyAwesomeString(): String {
val reference = SuperClass.Companion
return testFunction(reference::getMyString)
}
private fun testFunction(s: KFunction0<String>): String {
return s.invoke()
}
}
Don't know if it is possible to get the reference to super class's function, but here is an alternative to what you want to achieve:
override fun getString(): String = testFunction { super.getString() }
According to Bernardo's answer, you might have something like this. It doesn't have remarkable changes.
fun methodInActivity() {
runOnUiThread(this::config)
}
fun config(){
}
What is more, in the incoming 1.2 version you can use just
::config

Kotlin use Java callback interface

I have a WebView. I want to call
public void evaluateJavascript(String script, ValueCallback<String> resultCallback)
this method.
Here is the ValueCallback interface:
public interface ValueCallback<T> {
/**
* Invoked when the value is available.
* #param value The value.
*/
public void onReceiveValue(T value);
};
Here is my kotlin code:
webView.evaluateJavascript("a", ValueCallback<String> {
// cant override function
})
Anyone have idea to override the onReceiveValue method in kotlin?
I tried the "Convert Java to Kotlin" but result is the next:
v.evaluateJavascript("e") { }
Thanks!
The following line is called a SAM conversion:
v.evaluateJavascript("e", { value ->
// Execute onReceiveValue's code
})
Whenever a Java interface has a single method, Kotlin allows you to pass in a lambda instead of an object that implements that interface.
Since the lambda is the last parameter of the evaluateJavascript function, you can move it outside of the brackets, which is what the Java to Kotlin conversion did:
v.evaluateJavascript("e") { value ->
// Execute onReceiveValue's code
}
You already are. The content between your braces is the content of the onReceive function. Kotlin has automatic handling for SAM conversions from Java. All of the following are equivalent.
// Use Kotlin's SAM conversion
webView.evaluateJavascript("a") {
println(it) // "it" is the implicit argument passed in to this function
}
// Use Kotlin's SAM conversion with explicit variable name
webView.evaluateJavascript("a") { value ->
println(value)
}
// Specify SAM conversion explicitly
webView.evalueateJavascript("a", ValueCallback<String>() {
println(it)
})
// Use an anonymous class
webView.evalueateJavascript("a", object : ValueCallback<String>() {
override fun onReceiveValue(value: String) {
println(value)
}
})