2018-01-21 13:46:36 +01:00
|
|
|
|
@file:Suppress(
|
|
|
|
|
"USELESS_CAST", "unused", "DEPRECATED_IDENTITY_EQUALS", "UNUSED_VARIABLE",
|
|
|
|
|
"UNUSED_VALUE", "ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE", "VARIABLE_WITH_REDUNDANT_INITIALIZER",
|
|
|
|
|
"ReplaceCallWithComparison"
|
|
|
|
|
)
|
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
|
package jp.juggler.subwaytooter
|
|
|
|
|
|
|
|
|
|
import android.view.View
|
2018-01-11 10:31:25 +01:00
|
|
|
|
import org.junit.Test
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
import org.junit.Assert.*
|
|
|
|
|
import kotlin.concurrent.thread
|
2018-01-21 13:46:36 +01:00
|
|
|
|
|
2018-01-11 10:31:25 +01:00
|
|
|
|
//import kotlin.test.*
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
typealias TestLambdaCallback = (x : Int) -> Int
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
class TestKotlinFeature {
|
|
|
|
|
|
|
|
|
|
private val CODE_A = 1
|
|
|
|
|
private val CODE_A2 = 2
|
|
|
|
|
|
|
|
|
|
@Test
|
2018-01-21 13:46:36 +01:00
|
|
|
|
fun testWhenExpression() {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
// ifを式として扱えるように、whenも式として扱える
|
|
|
|
|
run {
|
|
|
|
|
val code = 2
|
|
|
|
|
val s = "prefix:" + when(code) {
|
|
|
|
|
CODE_A, CODE_A2 -> "a"
|
|
|
|
|
else -> "b"
|
|
|
|
|
} + ":suffix"
|
|
|
|
|
|
|
|
|
|
assertEquals("prefix:a:suffix", s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tryも式として扱える
|
|
|
|
|
run {
|
|
|
|
|
val p = try {
|
|
|
|
|
if(stringNull.isNullOrEmpty()) throw RuntimeException("foo")
|
|
|
|
|
true
|
|
|
|
|
} catch(ex : RuntimeException) {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
assertEquals(false, p)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private val stringNull : String? = null
|
|
|
|
|
private val stringEmpty : String? = ""
|
|
|
|
|
private val stringBlank : String? = " "
|
|
|
|
|
private val stringABC : String? = "ABC"
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testNullString() {
|
|
|
|
|
|
|
|
|
|
// Nullable型には値がnullでも呼び出せるメソッドがある
|
|
|
|
|
assertEquals(true, stringNull.isNullOrEmpty())
|
|
|
|
|
assertEquals(true, stringEmpty.isNullOrEmpty())
|
|
|
|
|
assertEquals(false, stringBlank.isNullOrEmpty())
|
|
|
|
|
assertEquals(false, stringABC.isNullOrEmpty())
|
|
|
|
|
|
|
|
|
|
assertEquals(true, stringNull.isNullOrBlank())
|
|
|
|
|
assertEquals(true, stringEmpty.isNullOrBlank())
|
|
|
|
|
assertEquals(true, stringBlank.isNullOrBlank())
|
|
|
|
|
assertEquals(false, stringABC.isNullOrBlank())
|
|
|
|
|
|
|
|
|
|
// ?. 演算子の後に プリミティブ型を返すメソッドを呼び出して、そのままifの条件式に指定する
|
|
|
|
|
// 「stringNull?.isNotEmpty()」の型はBoolean? なので trueと比較できるが、 ==true を省略することはできない
|
|
|
|
|
// true,false,null の3値論理になるので、条件を反転させたい場合は == false と != true で結果が異なる
|
|
|
|
|
assertEquals(0, if(stringNull?.isNotEmpty() == true) 1 else 0)
|
|
|
|
|
assertEquals(0, if(stringEmpty?.isNotEmpty() == true) 1 else 0)
|
|
|
|
|
assertEquals(1, if(stringBlank?.isNotEmpty() == true) 1 else 0)
|
|
|
|
|
assertEquals(1, if(stringABC?.isNotEmpty() == true) 1 else 0)
|
|
|
|
|
|
|
|
|
|
// isNotBlank で空白のみを含む文字列をfalseにできる
|
|
|
|
|
assertEquals(0, if(stringNull?.isNotBlank() == true) 1 else 0)
|
|
|
|
|
assertEquals(0, if(stringEmpty?.isNotBlank() == true) 1 else 0)
|
|
|
|
|
assertEquals(0, if(stringBlank?.isNotBlank() == true) 1 else 0)
|
|
|
|
|
assertEquals(1, if(stringABC?.isNotBlank() == true) 1 else 0)
|
|
|
|
|
|
|
|
|
|
if(! stringABC.isNullOrEmpty()) {
|
|
|
|
|
// このブロック内部で string がまだNullableとして扱われるのが残念極まりない
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// コンパイラに予測できない方法でIntの10を生成する
|
|
|
|
|
private fun generate10A() : Int {
|
|
|
|
|
return ("1" + "0").toInt()
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// コンパイラに予測できない方法でIntの10を生成する
|
|
|
|
|
private fun generate10B() : Int {
|
|
|
|
|
var i = 0
|
|
|
|
|
while(true) {
|
|
|
|
|
++ i
|
|
|
|
|
if(i % 5 == 0 && i % 2 == 0) return i
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testOperator() {
|
|
|
|
|
// is 演算子と !is 演算子
|
|
|
|
|
open class A(val name : String = "nanasi")
|
|
|
|
|
|
|
|
|
|
class B(name : String = "nanasi", val count : Int = 0) : A(name)
|
|
|
|
|
class C
|
|
|
|
|
|
|
|
|
|
val b = B("b", 10)
|
|
|
|
|
val c = C()
|
|
|
|
|
assertEquals(true, b as Any is A)
|
|
|
|
|
assertEquals(true, c as Any !is A)
|
|
|
|
|
|
|
|
|
|
// in 演算子と !in 演算子
|
|
|
|
|
val range1 = 0 .. 10
|
|
|
|
|
val range2 = 0 until 10 // 10を含まない。 until は言語機能ではなく infix関数
|
|
|
|
|
assertEquals(true, 10 in range1)
|
|
|
|
|
assertEquals(true, 10 !in range2)
|
|
|
|
|
|
|
|
|
|
// ==,=== 演算子とプリミティブ型
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val long10 = 10L
|
|
|
|
|
val int10 = 10
|
2018-01-04 19:52:25 +01:00
|
|
|
|
val int10b : Int = generate10A()
|
|
|
|
|
val int10c : Int = generate10B()
|
|
|
|
|
|
|
|
|
|
// IntとLongを直接比較しようとするとコンパイルエラーになる
|
|
|
|
|
// assertEquals( true, int10 == long10 )
|
|
|
|
|
|
|
|
|
|
// 型が分からないようにするとビルドできるが、intの10とlongの10は異なると判断される
|
|
|
|
|
// Int.equals も同じ結果
|
|
|
|
|
assertEquals(false, int10 as Any == long10 as Any)
|
2021-05-08 07:56:34 +02:00
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
|
// Long.equals でも同じ結果
|
|
|
|
|
assertEquals(false, long10 as Any == int10 as Any)
|
2021-05-08 07:56:34 +02:00
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
|
// 同じ型に変換すると数値が同じだと判定できる
|
|
|
|
|
assertEquals(true, int10.toLong() == long10)
|
2020-09-09 21:46:50 +02:00
|
|
|
|
assertEquals(true, int10.toLong() == long10)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
// === 演算子 とプリミティブ型
|
|
|
|
|
|
|
|
|
|
// 型が違うとコンパイルエラー
|
|
|
|
|
// assertEquals( true, int10 === long10 )
|
|
|
|
|
|
|
|
|
|
// 型が同じでも記述した時点で deprecatedという警告が出る。
|
|
|
|
|
// クラスファイルを読むと if_icmpne を使って数値比較していた。equalsではない
|
|
|
|
|
assertEquals(true, int10 === int10b)
|
|
|
|
|
assertEquals(true, int10 === int10c)
|
|
|
|
|
assertEquals(true, int10 === 10)
|
|
|
|
|
assertEquals(true, int10 === generate10A())
|
|
|
|
|
|
|
|
|
|
// Any型に変換して比較。警告はでない
|
|
|
|
|
// Anyへのキャストは java/lang/Integer.valueOf でboxingしてから checkcast java/lang/Objectして if_acmpne していた
|
|
|
|
|
assertEquals(true, int10 as Any === int10b as Any)
|
|
|
|
|
assertEquals(true, int10 as Any === int10c as Any)
|
|
|
|
|
assertEquals(true, int10 as Any === 10 as Any)
|
|
|
|
|
assertEquals(true, int10 as Any === generate10A() as Any)
|
|
|
|
|
|
|
|
|
|
// valueOfは-128..127は内部でキャッシュを行うから、値によっては同じアドレスだったり異なったりする
|
2018-01-21 13:46:36 +01:00
|
|
|
|
var intA = 0
|
|
|
|
|
var intB = 0
|
2018-01-04 19:52:25 +01:00
|
|
|
|
for(i in 126 .. 127) {
|
|
|
|
|
println("i=$i")
|
|
|
|
|
intA = i
|
|
|
|
|
intB = i
|
|
|
|
|
assertEquals(true, intA as Any === intB as Any)
|
|
|
|
|
}
|
|
|
|
|
for(i in 128 .. 130) {
|
|
|
|
|
println("i=$i")
|
|
|
|
|
intA = i
|
|
|
|
|
intB = i
|
|
|
|
|
assertEquals(false, intA as Any === intB as Any)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
蛇足だが、クラスファイルを読むのは
|
|
|
|
|
app/build/tmp/kotlin-classes/*UnitTest\**/TestKotlinFeature.class を
|
2018-01-28 20:03:04 +01:00
|
|
|
|
javap.exe -c TestKotlinFeature.class > javap.warning とすると逆アセンブルできる
|
2018-01-04 19:52:25 +01:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testNullableIf() {
|
|
|
|
|
|
|
|
|
|
// Boolean? は true false null の3値論理となる
|
|
|
|
|
// stringNull?.isNotEmpty() など、 ?.演算子を使うと Nullable型が発生するシチュエーションがよくある
|
|
|
|
|
|
|
|
|
|
val nullableTrue : Boolean? = true
|
|
|
|
|
val nullableFalse : Boolean? = false
|
|
|
|
|
val nullableNull : Boolean? = null
|
|
|
|
|
|
|
|
|
|
// ifの条件式部分は Boolean? の値を直接扱うことはできない。コンパイルエラーとなる
|
|
|
|
|
// assertEquals( 1 , if( nullableTrue ) 1 else 0 )
|
|
|
|
|
// assertEquals( 1 , if( nullableFalse ) 1 else 0 )
|
|
|
|
|
// assertEquals( 1 , if( nullableNull ) 1 else 0 )
|
|
|
|
|
|
|
|
|
|
// == != 演算子はnullを取り扱える
|
|
|
|
|
assertEquals(1, if(nullableTrue == true) 1 else 0)
|
|
|
|
|
assertEquals(0, if(nullableTrue == false) 1 else 0)
|
|
|
|
|
assertEquals(0, if(nullableTrue == null) 1 else 0)
|
|
|
|
|
assertEquals(0, if(nullableTrue != true) 1 else 0)
|
|
|
|
|
assertEquals(1, if(nullableTrue != false) 1 else 0)
|
|
|
|
|
assertEquals(1, if(nullableTrue != null) 1 else 0)
|
|
|
|
|
|
|
|
|
|
assertEquals(0, if(nullableFalse == true) 1 else 0)
|
|
|
|
|
assertEquals(1, if(nullableFalse == false) 1 else 0)
|
|
|
|
|
assertEquals(0, if(nullableFalse == null) 1 else 0)
|
|
|
|
|
assertEquals(1, if(nullableFalse != true) 1 else 0)
|
|
|
|
|
assertEquals(0, if(nullableFalse != false) 1 else 0)
|
|
|
|
|
assertEquals(1, if(nullableFalse != null) 1 else 0)
|
|
|
|
|
|
|
|
|
|
assertEquals(0, if(nullableNull == true) 1 else 0)
|
|
|
|
|
assertEquals(0, if(nullableNull == false) 1 else 0)
|
|
|
|
|
assertEquals(1, if(nullableNull == null) 1 else 0)
|
|
|
|
|
assertEquals(1, if(nullableNull != true) 1 else 0)
|
|
|
|
|
assertEquals(1, if(nullableNull != false) 1 else 0)
|
|
|
|
|
assertEquals(0, if(nullableNull != null) 1 else 0)
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
interface MyKotlinInterface {
|
2020-09-09 21:46:50 +02:00
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
fun method(x : Int) : Int
|
2018-01-04 19:52:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testSAM() {
|
|
|
|
|
|
|
|
|
|
// 定義例(文脈あり)
|
2020-09-09 21:46:50 +02:00
|
|
|
|
Thread { println("SAM 1") }.start()
|
2018-01-21 13:46:36 +01:00
|
|
|
|
Thread { println("SAM 2") }.start()
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
// 定義例(文脈不明)
|
2020-09-09 21:46:50 +02:00
|
|
|
|
val a = Runnable { println("SAM a") }
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
// 参照型の定義
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val ref : Runnable = a
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
// 参照型の呼び出し
|
|
|
|
|
ref.run()
|
|
|
|
|
|
|
|
|
|
// Nullableな参照型の定義
|
|
|
|
|
val refNullable : Runnable? = a
|
2018-01-21 13:46:36 +01:00
|
|
|
|
if(refNullable != null) {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
// 呼び出し
|
|
|
|
|
Thread(refNullable).start()
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-09 21:46:50 +02:00
|
|
|
|
View.OnClickListener { println("clicked") }.onClick(null)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
// kotlinで定義したインタフェースに対してSAMコンストラクタを使えるか?
|
|
|
|
|
// ダメでした
|
2018-01-21 13:46:36 +01:00
|
|
|
|
// val ki = MyKotlinInterface{
|
|
|
|
|
// it * it
|
|
|
|
|
// }
|
2018-01-04 19:52:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testLambda() {
|
|
|
|
|
// 定義例(文脈あり)
|
2018-01-21 13:46:36 +01:00
|
|
|
|
thread(start = true) { println("testLambda") }
|
|
|
|
|
println(10.let { x -> x * x })
|
2020-09-09 21:46:50 +02:00
|
|
|
|
println(10)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
// 定義例(文脈不明)
|
|
|
|
|
val a = { println("testLambda") }
|
|
|
|
|
|
|
|
|
|
// 参照型の定義
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val ref : (x : Int) -> Int = { it * it }
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
// 参照型の呼び出し
|
2018-01-21 13:46:36 +01:00
|
|
|
|
println(ref(10))
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
// 参照型の定義(Nullable)
|
|
|
|
|
val refNullable : TestLambdaCallback? = { it * it }
|
2018-01-21 13:46:36 +01:00
|
|
|
|
if(refNullable != null) {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
refNullable(10)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testAnonymousFunction() {
|
2018-01-10 16:47:35 +01:00
|
|
|
|
// 定義例(文脈あり)
|
2018-01-21 13:46:36 +01:00
|
|
|
|
thread(start = true, block = fun() { println("testAnonymousFunction") })
|
|
|
|
|
println(10.let(fun(x : Int) = x * x))
|
2020-09-09 21:46:50 +02:00
|
|
|
|
println(10)
|
2018-01-10 16:47:35 +01:00
|
|
|
|
// 定義例(文脈不明)
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val a = fun(x : Int) = x * x
|
2018-01-10 16:47:35 +01:00
|
|
|
|
|
|
|
|
|
// 参照型の定義
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val ref : (x : Int) -> Int = a
|
2018-01-10 16:47:35 +01:00
|
|
|
|
|
|
|
|
|
// 参照型の呼び出し
|
2018-01-21 13:46:36 +01:00
|
|
|
|
println(ref(10))
|
2018-01-10 16:47:35 +01:00
|
|
|
|
|
|
|
|
|
// 参照型の定義(Nullable)
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val refNullable : TestLambdaCallback? = fun(i : Int) = i * i
|
|
|
|
|
if(refNullable != null) {
|
2018-01-10 16:47:35 +01:00
|
|
|
|
refNullable(10)
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testObjectExpression() {
|
|
|
|
|
// 定義例(文脈あり)
|
|
|
|
|
abstract class Base {
|
2018-01-21 13:46:36 +01:00
|
|
|
|
|
|
|
|
|
abstract fun method(x : Int) : Int
|
2018-01-04 19:52:25 +01:00
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
|
|
|
|
|
val a = object : Base() {
|
|
|
|
|
override fun method(x : Int) : Int {
|
|
|
|
|
return x * x
|
2018-01-04 19:52:25 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
|
// 定義例(文脈の有無で変化しない)
|
|
|
|
|
// 参照型の定義
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val ref : Base = a
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
// 参照型の定義(Nullable)
|
|
|
|
|
val refNullable : Base? = a
|
2018-01-21 13:46:36 +01:00
|
|
|
|
if(refNullable != null) {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
val v = refNullable.method(10)
|
|
|
|
|
println("OE v=$v")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
fun caller(b : Base) {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
val v = b.method(10)
|
|
|
|
|
println("OE b $v")
|
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
caller(object : Base() {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
override fun method(x : Int) : Int {
|
2018-01-21 13:46:36 +01:00
|
|
|
|
return x * x * x
|
2018-01-04 19:52:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
private fun member(x : Int) = x * x
|
2020-09-09 21:46:50 +02:00
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
|
@Test
|
|
|
|
|
fun testMemberReference() {
|
2018-01-21 13:46:36 +01:00
|
|
|
|
fun caller(a : (receiver : TestKotlinFeature, x : Int) -> Int) {
|
|
|
|
|
val v = a(this, 10)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
println("testMemberReference caller $v")
|
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
caller(TestKotlinFeature::member)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
|
|
val b = TestKotlinFeature::member
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val a : (receiver : TestKotlinFeature, x : Int) -> Int = TestKotlinFeature::member
|
2018-01-04 19:52:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
fun methodNotInline(callback : (x : Int) -> Int) : Int {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
return callback(3)
|
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
|
|
|
|
|
inline fun methodInline(callback : (x : Int) -> Int) : Int {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
return callback(5)
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
@Test
|
|
|
|
|
fun testReturn() {
|
|
|
|
|
|
|
|
|
|
// loop@ for( i in 1..2) {
|
|
|
|
|
// // 関数の引数以外の場所で定義したラムダ式
|
|
|
|
|
// var x = { x : Int ->
|
|
|
|
|
// break // コンパイルエラー
|
|
|
|
|
// break@loop // コンパイルエラー
|
|
|
|
|
// // return // コンパイルエラー
|
|
|
|
|
// x * x
|
|
|
|
|
// }(10)
|
|
|
|
|
// println("testReturn A:$x")
|
|
|
|
|
//
|
|
|
|
|
// // 非インライン関数の引数として定義したラムダ式
|
|
|
|
|
// x = methodNotInline { x : Int ->
|
|
|
|
|
// break // コンパイルエラー
|
|
|
|
|
// break@loop // コンパイルエラー
|
|
|
|
|
//
|
|
|
|
|
// // return // コンパイルエラー
|
|
|
|
|
//
|
|
|
|
|
// return@methodNotInline x * x
|
|
|
|
|
// }
|
|
|
|
|
// println("testReturn B:$x")
|
|
|
|
|
//
|
|
|
|
|
// // インライン関数の引数として定義したラムダ式
|
|
|
|
|
// methodInline { x : Int ->
|
|
|
|
|
// break // コンパイルエラー
|
|
|
|
|
// break@loop // コンパイルエラー
|
|
|
|
|
//
|
|
|
|
|
// return 10 // できる
|
|
|
|
|
//
|
|
|
|
|
// return@methodInline 10 // できる
|
|
|
|
|
// }
|
|
|
|
|
// }
|
2018-01-04 19:52:25 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
private fun <A, B> A.letNotInline(code : (A) -> B) : B {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
return code(this)
|
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testInline0() {
|
|
|
|
|
var result : Int
|
2018-01-04 19:52:25 +01:00
|
|
|
|
val n = 11
|
2018-01-21 13:46:36 +01:00
|
|
|
|
for(i in 1 .. 10) {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
println(n.letNotInline { v ->
|
|
|
|
|
val rv = v * i
|
|
|
|
|
result = rv
|
|
|
|
|
rv
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testInline1() {
|
|
|
|
|
var result : Int
|
2018-01-04 19:52:25 +01:00
|
|
|
|
val n = 12
|
2018-01-21 13:46:36 +01:00
|
|
|
|
for(i in 1 .. 10) {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
println(n.let { v ->
|
|
|
|
|
val rv = v * i
|
|
|
|
|
result = rv
|
|
|
|
|
rv
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
@Test
|
|
|
|
|
fun testInline2() {
|
|
|
|
|
var result : Int
|
2018-01-04 19:52:25 +01:00
|
|
|
|
val n = 13
|
2018-01-21 13:46:36 +01:00
|
|
|
|
for(i in 1 .. 10) {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
val rv = n * i
|
|
|
|
|
result = rv
|
|
|
|
|
println(rv)
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
fun testRawArray() {
|
2018-01-10 16:47:35 +01:00
|
|
|
|
// サイズを指定して生成
|
|
|
|
|
val a = IntArray(4)
|
2020-09-09 21:46:50 +02:00
|
|
|
|
for(i in a.indices) {
|
2018-01-21 13:46:36 +01:00
|
|
|
|
a[i] = i * 2
|
2018-01-10 16:47:35 +01:00
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
println(a.joinToString(","))
|
2018-01-10 16:47:35 +01:00
|
|
|
|
|
|
|
|
|
// サイズと初期化ラムダを指定して生成
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val b = IntArray(4) { index -> index * 3 }
|
|
|
|
|
println(b.joinToString(","))
|
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
|
// 可変長引数で初期化するライブラリ関数
|
2018-01-21 13:46:36 +01:00
|
|
|
|
var b2 = intArrayOf(0, 1, 2, 3)
|
2018-01-10 16:47:35 +01:00
|
|
|
|
|
|
|
|
|
// 参照型の配列だと初期化ラムダが必須
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val c = Array<CharSequence>(4) { (it * 4).toString() }
|
|
|
|
|
println(c.joinToString(","))
|
|
|
|
|
val d = Array<CharSequence?>(4) { if(it % 2 == 0) null else (it * 5).toString() }
|
|
|
|
|
println(d.joinToString(","))
|
2018-01-10 16:47:35 +01:00
|
|
|
|
|
|
|
|
|
// ラムダ式の戻り値の型から配列の型パラメータが推測される
|
2018-01-21 13:46:36 +01:00
|
|
|
|
val e = Array(4) { if(it % 2 == 0) null else (it * 6).toString() }
|
|
|
|
|
println(e.joinToString(","))
|
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
|
// 可変長引数で初期化するライブラリ関数
|
2018-01-21 13:46:36 +01:00
|
|
|
|
var e2 = arrayOf(null, 1, null, 2)
|
2018-01-10 16:47:35 +01:00
|
|
|
|
|
|
|
|
|
}
|
2018-01-20 07:51:14 +01:00
|
|
|
|
|
2018-01-21 13:46:36 +01:00
|
|
|
|
@Test
|
|
|
|
|
fun testOutProjectedType() {
|
|
|
|
|
fun foo(args : Array<out Number>) {
|
2018-01-20 07:51:14 +01:00
|
|
|
|
val sb = StringBuilder()
|
2018-01-21 13:46:36 +01:00
|
|
|
|
for(s in args) {
|
2018-01-20 07:51:14 +01:00
|
|
|
|
if(sb.isNotEmpty()) sb.append(',')
|
|
|
|
|
sb
|
|
|
|
|
.append(s.toString())
|
|
|
|
|
.append('#')
|
2018-01-21 13:46:36 +01:00
|
|
|
|
.append(s.javaClass.simpleName)
|
2018-01-20 07:51:14 +01:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
println(sb)
|
|
|
|
|
println(args.contains(6)) // 禁止されていない。inポジションって何だ…?
|
2020-09-09 21:46:50 +02:00
|
|
|
|
// args[0]=6 //禁止されている
|
2018-01-20 07:51:14 +01:00
|
|
|
|
}
|
2018-01-21 13:46:36 +01:00
|
|
|
|
foo(arrayOf(1, 2, 3))
|
|
|
|
|
foo(arrayOf(1f, 2f, 3f))
|
2018-01-20 07:51:14 +01:00
|
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
|
}
|