Skip to content

Instantly share code, notes, and snippets.

@taichi
Created February 28, 2016 14:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save taichi/2bd0fdbabbe977ed34e3 to your computer and use it in GitHub Desktop.
Save taichi/2bd0fdbabbe977ed34e3 to your computer and use it in GitHub Desktop.
Kotlin SAM type conversion
buildscript {
ext.kotlin_version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id 'java'
id 'idea'
}
apply plugin: "kotlin"
repositories {
maven {
url 'https://maven-central.storage.googleapis.com'
}
jcenter()
mavenCentral()
}
sourceCompatibility = targetCompatibility = 1.8
tasks.withType(SourceTask).findAll { it.hasProperty('options') } *.options*.encoding = 'UTF-8'
test {
systemProperty('java.awt.headless', true)
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
//compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}
package aaa;
public interface JavaSAM {
String doIt(int i, String s);
static void call(JavaSAM ms) {
System.out.println(ms.doIt(1, "zzzz"));
}
}
package aaa
interface KtSAM {
fun done(i: Int, s: String?): String?
}
package aaa
fun main(args: Array<String>) {
java_interop()
sam_conversions()
anonymous_sam_conversions()
kotlin_not_support_sam_conversions()
function_types()
}
fun java_interop() {
// IntelliJ says me `Convert to Lambda`
JavaSAM.call(object : JavaSAM {
override fun doIt(i: Int, s: String?): String? {
return "zzz$i$s"
}
})
JavaSAM.call { i: Int, s: String? -> "zzz$i$s" }
JavaSAM.call { i, s -> "zzz$i$s" }
}
// https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
fun callJavaSAM(sam: JavaSAM) = println(sam.doIt(1, "a"))
fun sam_conversions() {
val ms0: JavaSAM = JavaSAM { i: Int, s: String? -> "zzz$i$s" }
callJavaSAM(ms0)
val ms1 = JavaSAM { i: Int, s: String? -> "zzz$i$s" }
callJavaSAM(ms1)
// error why?. types are completely match but conversion is not work.
val ms2: JavaSAM = { i: Int, s: String? ->
if (i < 0) {
null
} else {
"zzz$i$s"
}
}
callJavaSAM(ms2)
val ms3 = JavaSAM { i, s -> "zzz$i$s" }
callJavaSAM(ms3)
// error but ok. types are ambiguous
val ms4: JavaSAM = { i, s -> "zzz$i$s" }
callJavaSAM(ms4)
}
fun anonymous_sam_conversions() {
// IntelliJ says me `Convert to Lambda`
callJavaSAM(object : JavaSAM { // (1)
override fun doIt(i: Int, s: String?): String? {
return "zzz$i$s"
}
})
callJavaSAM(JavaSAM { i: Int, s: String? -> "zzz$i" })// (2)
callJavaSAM(JavaSAM { i, s -> "zzz$i" }) // (3)
callJavaSAM { i: Int, s: String? -> "zzz$i" } // (4)
callJavaSAM { i, s -> "zzz$i" } // (5)
}
fun callKtSAM(sam: KtSAM) = println(sam.done(2, "b"))
fun kotlin_not_support_sam_conversions() {
val ms0 = object : KtSAM {
override fun done(i: Int, s: String?): String? = "zzz$i$s"
}
callKtSAM(ms0)
callKtSAM(object : KtSAM {
override fun done(i: Int, s: String?): String? = "zzz$i$s"
})
// error. SAM conversions works only for Java interop
val ms1 = KtSAM { i, s -> "zzz$i$s" }
callKtSAM(ms1)
callKtSAM(KtSAM { i, s -> "zzz$i$s" })
}
fun kotlin_fake_sam_conversions() {
// but define adapter function.
fun KtSAM(fn: (i: Int, s: String?) -> String?) = object : KtSAM {
override fun done(i: Int, s: String?): String? = fn(i, s)
}
val ms2 = KtSAM({ i, s -> "zzz$i$s" })
callKtSAM(ms2)
val ms3 = KtSAM { i, s -> "zzz$i$s" }
callKtSAM(ms3)
callKtSAM(KtSAM { i, s -> "zzz$i$s" })
}
fun call(fn: (Int, String?) -> String?) = println(fn(3, "c"))
fun function_types() {
val fn: (Int, String?) -> String? = { i, s -> "zzz$i$s" }
call(fn)
call { i: Int, s: String? -> "zzz$i$s" }
call { i, s -> "zzz$i$s" }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment