内容へ移動
猫型iPS細胞研究所
ユーザ用ツール
ログイン
サイト用ツール
検索
ツール
文書の表示
以前のリビジョン
バックリンク
最近の変更
メディアマネージャー
サイトマップ
ログイン
>
最近の変更
メディアマネージャー
サイトマップ
現在位置:
INDEX
»
kotlin
»
Kotlinプログラミング
トレース:
kotlin:kotlinプログラミング
この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。
====== Kotlinプログラミング ====== [[https://www.amazon.co.jp/gp/product/4798160199/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4798160199&linkCode=as2&tag=ipsnekotypeco-22&linkId=abf7623ae11e3edcda307497058d8787| Kotlinプログラミング]] ===== 4.10 Nothing型 ===== TODO():Nothingなので、 - 関数本体でTODO()を使うと何も返さないことを保証する。それでコンパイラはチェックをしない。関数の実装をしなくても、作業ができる。 - TODO()に続くコードは到達不能にできる。 <code kotlin> fun shouldReturnAString():String{ TODO("まだ開発途中") println("TODOのした") //到達しない } </code> ===== 15.4 列挙クラス ===== [[kotlin:enumとsealed|]] <code kotlin> enum class Direction() { NORTH, EAST, SOUTH, WEST } fun main(){ println("Direction.NORTH = ${Direction.NORTH}") println("Direction.NORTH.name = ${Direction.NORTH.name}") println("Direction.NORTH.ordinal = ${Direction.NORTH.ordinal}") println("Direction.EAST = ${Direction.EAST}") println("Direction.EAST.name = ${Direction.EAST.name}") println("Direction.EAST.ordinal = ${Direction.EAST.ordinal}") } ↓ Direction.NORTH = NORTH Direction.NORTH.name = NORTH Direction.NORTH.ordinal = 0 Direction.EAST = EAST Direction.EAST.name = EAST Direction.EAST.ordinal = 1 </code> <code kotlin> enum class Direction(val x:Int,val y:Int) { NORTH(0,-1), EAST(1,0), SOUTH(0,1), WEST(-1,0) } fun main(){ println("Direction.NORTH.x = ${Direction.NORTH.x}") println("Direction.NORTH.y = ${Direction.NORTH.y}") println("Direction.NORTH = ${Direction.NORTH}") println("Direction.NORTH.name = ${Direction.NORTH.name}") println("Direction.NORTH.ordinal = ${Direction.NORTH.ordinal}") println("Direction.EAST.x = ${Direction.EAST.x}") println("Direction.EAST.y = ${Direction.EAST.y}") println("Direction.EAST = ${Direction.EAST}") println("Direction.EAST.name = ${Direction.EAST.name}") println("Direction.EAST.ordinal = ${Direction.EAST.ordinal}") } ↓ Direction.NORTH.x = 0 Direction.NORTH.y = -1 Direction.NORTH = NORTH Direction.NORTH.name = NORTH Direction.NORTH.ordinal = 0 Direction.EAST.x = 1 Direction.EAST.y = 0 Direction.EAST = EAST Direction.EAST.name = EAST Direction.EAST.ordinal = 1 </code> ===== 17.1 ジェネリック型を定義する ===== ジェネリック型とはどんな型でも入力として受けとるコンストラクタを持つ型。 Class Class名<T>(xxxx:T) <code kotlin> class LootBox<T>(var item:T) class Fedora(val name:String,val value:Int) class Coin(val value:Int) fun main(){ // ジェネリックを使っているのでFedoraでもCoinでもいれることができる val lootBoxOne:LootBox<Fedora> = LootBox(Fedora("general-fedora",15)) val lootBoxTow:LootBox<Coin> = LootBox(Coin(15)) } </code> ===== 17.2 ジェネリック関数 ===== <code kotlin> class LootBox<T>(var item:T){ fun fetch():T{ //関数でもジェネリックが使える return item } } class Fedora(val name:String,val value:Int) class Coin(val value:Int) fun main(){ // ジェネリックを使っているのでFedoraでもCoinでもいれることができる val lootBoxOne:LootBox<Fedora> = LootBox(Fedora("general-fedora",15)) val lootBoxTow:LootBox<Coin> = LootBox(Coin(15)) lootBoxOne.fetch().run { println("You Retrive $name") } } ↓ You Retrive general-fedora </code> ===== 17.3 複数のジェネリック型パラメータ ===== fun <R> 関数名():R <code kotlin> class LootBox<T>(var item:T){ fun fetch():T{ return item } fun <R> fetch(lootFunction:(T)->R):R{ //戻り値に新しいジェネリックを追加 return lootFunction(item) } } class Fedora(val name:String,val value:Int) class Coin(val value:Int) fun main(){ // ジェネリックを使っているのでFedoraでもCoinでもいれることができる val lootBoxOne:LootBox<Fedora> = LootBox(Fedora("general-fedora",15)) val lootBoxTow:LootBox<Coin> = LootBox(Coin(15)) //val price = lootBoxOne.fetch<Int>({it.value*5}) //val price = lootBoxOne.fetch<Int>(){it.value*5} //ラムダの引数は外にだす val price = lootBoxOne.fetch(){it.value*5} //型の<Int>は省略できる println(price) } </code> ===== 17.4 ジェネリック型の制約 ===== <code kotlin> class LootBox<T:Loot>(var item:T){ //<T>を<T:Loot>とすることでジェネリック型の制約ができる。 fun fetch():T{ return item } } open class Loot(val value:Int) class Fedora(val name:String,value:Int):Loot(value) //FedoraはLootのサブクラス class Coin(value:Int) // Coinはサブクラスではない fun main(){ val lootBoxOne:LootBox<Loot> = LootBox(Fedora("general-fedora",15)) //FedoraはサブクラスなのでLoot型の箱に入る。 //val fedora:Fedora = lootBoxOne.item // Error Required:Fedora Found:Loot // Loot型の箱に入れるとFedoraという情報は消える //val lootBoxTwo = LootBox(Coin(15))} // CoinはLootのサブクラスではないので箱にははいらなくなった。←ジェネリック型の制約 </code> ===== 17.6 in と out ===== <WRAP center round tip 100%> ジェネリック不変なので下記コードはエラーとなることが大前提! val lootOnebox = LootBox(Fedora("cool-Fedora!",30)) val lootBox:LootBox<Loot> = lootOnebox //ジェネリックは不変 </WRAP> <code kotlin> // このコードはエラー!! class LootBox<T>(val item:T){ // outが必要 } open class Loot(val value:Int) class Fedora(val name:String,value:Int):Loot(value) //Lootのサブクラス class Coin(value:Int):Loot(value) //Lootのサブクラス fun main() { val coinBox:LootBox<Coin> = LootBox(Coin(15)) val lootBox1:LootBox<Loot> = coinBox //ジェネリック型は不変なのでエラー!! LootBox<Loot> LootBox<Coin> val lootBox2:LootBox<Loot> = LootBox(Coin(15)) // これはインスタンスの代入ではないのでoutがなくても可能。 } </code> ↓ <code kotlin> class LootBox<out T>(val item:T){ //outをつけるとコンパイルが通る。outにするとvarにはできない。 } open class Loot(val value:Int) class Fedora(val name:String,value:Int):Loot(value) //Lootのサブクラス class Coin(value:Int):Loot(value) //Lootのサブクラス fun main() { val coinBox:LootBox<Coin> = LootBox(Coin(15)) val lootBox:LootBox<Loot> = coinBox // コンパイルできる!が、Coinの情報はなくなりLootになる。 } </code> <WRAP center round tip 100%> // 不変によりLootBox<Fedora>型のインスタンスをLootBox<Loot>型に代入することはできない。 val lootOnebox = LootBox(Fedora("cool-Fedora!",30)) val lootBox:LootBox<Loot> = lootOnebox //←エラー。outを使う必要がある。 // しかしLootBox<Loot>型を使ってFedoraの初期値をもつLootBoxのインスタンスを成することはできる。 // 作成した段階で、Fedoraの情報は失われてLootBox<Loot>型のインスタンスとなる。 val lootBoxThird:LootBox<Loot> = LootBox(Fedora("cool-Fedora!",30)) // ←正常 </WRAP> ↓スマートキャスト <code kotlin> class LootBox<out T>(val item:T){ //outをつける!! } open class Loot(val value:Int) class Fedora(val name:String,value:Int):Loot(value) //Lootのサブクラス class Coin(value:Int):Loot(value) //Lootのサブクラス fun main() { val fedorBox = LootBox(Fedora("cool-Fedora!",30)) var lootBox:LootBox<Loot> = LootBox(Coin(10)) val myLoot = lootBox.item // Coin型ではなくLoot型にスマートキャストされる lootBox=fedorBox // outがないとLootBxo<Loot>にLootBox<Fedora>は代入できない。 val myFedora = lootBox.item //LootBox<Loot>だが、Fedora型へスマートキャストできる! } </code> <code kotlin> class LootBox<in T>(item:T){ //inをつけるとvalやvarはつけれれない。プロパティとなり値を返してしまう(生産者となる)から。 // private var loot = item // fun fetch():T{ //inがあるとこのような関数も作成できない // return loot // } } open class Loot(val value:Int) class Fedora(val name:String,value:Int):Loot(value) //Lootのサブクラス class Coin(value:Int):Loot(value) //Lootのサブクラス fun main() { var fedorBox = LootBox(Fedora("cool-Fedora!",30)) var lootBox:LootBox<Loot> = LootBox(Coin(10)) fedorBox = lootBox //in があるとLootBox<Fedora>型にLootBxo<Loot>が代入できる // val myFedora = fedorBox.item //エラー!inがあるので生産できない! } </code> ===== 17.6.補足 in と out ===== そもそも通常のインスタンスの場合は、上位クラス = 下位クラス は可能。 ジェネリック型の場合は、同じレベルのクラス = 同じレベルのクラス が基本(=不変)。 <code kotlin> class LootBox<T>(val item:T){ //inをつけるとvalやvarはつけれれない。プロパティとなり値を返してしまう(生産者)から。 } open class Loot(val value:Int) class Fedora(val name:String,value:Int):Loot(value) class Coin(value:Int):Loot(value) fun main() { // Loot型にcoin型をいれることはできる。 val coinItem:Coin = Coin(15) val LootItem:Loot = coinItem // ジェネリック型にcoin型をいれることはできない。不変! val coinBox = LootBox(Coin(20)) val lootBox:LootBox<Loot> = coinBox // type mismatchでエラー。LootBox<out T>にする必要がある。 ↓ // キャストすることも可能だが、UnChecked Castと警告がでる。 val lootBox:LootBox<Loot> = coinBox as LootBox<Loot> } </code> outはLootBox<Loot>型を指定して、LootBox<Coin>型のインスタンスがつくれないというはなしではない。 もしそうしても、LootBox<Loot>型のインスタンスが作成されるだけだ。 LootBox<Loot>型のインスタンスにLootBox<Coin>型のインスタンスを代入できない。 <Loot>型なのに中身が<Coin>型や<Fedora>型になってしまうため。 <code kotlin> class LootBox<T>(val item:T){ } open class Loot(val value:Int) class Fedora(val name:String,value:Int):Loot(value) class Coin(value:Int):Loot(value) fun main() { // outがなくてもLootBox<Loot>型でLootBox<Coin>型を作ることはできる。 val lootBox1:LootBox<Loot> = LootBox(Coin(10)) val coin1:Coin = lootBox1.item // エラー。Coin型の情報はなくなり、Loot型になっている。 val coin2:Coin = lootBox1.item as Coin // キャストしてやれば取り出せる。 //LootBox<Coin>でインスタンスを作成したものをLootBox<Loot>型に変換できない。 val coinBox = LootBox(Coin(20)) val lootBox2:LootBox<Loot> = coinBox //エラー。 LootBox<out T>(val item:T)にする必要がある。 ↓ // outをつけると下記コードは通り、LootBox<Coin>型からLootBox<Loot>へ変換される。 val lootBox2:LootBox<Loot> = coinBox } </code> ===== 17.7 もっと知りたい? reifiedキーワード ===== ジェネリック型は型消去されて実行時に型情報を利用できない。 <code kotlin> class LootBox<T>(val item:T){ } open class Loot(val value:Int) class Fedora(val name:String,value:Int):Loot(value) //Lootのサブクラス class Coin(value:Int):Loot(value) //Lootのサブクラス inline fun <reified T> randomOrBackupLoot(backupLoot:()->T):T { //reifiedにはinlineが必要 val items = listOf(Coin(14), Fedora("good-fedora", 20)) val randomLoot: Loot = items.shuffled().first() return if (randomLoot is T){ //reifiedがないとTでエラー randomLoot }else{ backupLoot() } } fun main() { randomOrBackupLoot { Fedora("backup-fedora",99) }.run { println("$name") } } </code> ===== 19.3 シーケンス ===== <code> fun <T : Any> generateSequence( seed: T?, nextFunction: (T) -> T? ): Sequence<T> ↓ generateSequence([初期値],[ラムダ]) ↓ generateSequence([初期値]){[ラムダ]} </code> <code kotlin> fun Int.isEven():Boolean{ return this%2==0 } val seq = generateSequence(1) { it+1 }.take(10).filter { it.isEven() }.toList() println(seq) [2, 4, 6, 8, 10] </code> <code kotlin> // seedはまずプリントされてから増加する generateSequence(1){it+1}.take(10).forEach { println(it) } 1 2 3 </code> ===== 19.6 チャンレンジ! Mapのキーと値の関係を逆転させる ===== <code kotlin> val gradesByStudent = mapOf("Josh" to 4.0,"Alex" to 2.0,"Jane" to 3.0) println(gradesByStudent) val reverseGradesByStudent= gradesByStudent.map { Pair(it.value,it.key) }.toMap() print(reverseGradesByStudent) {Josh=4.0, Alex=2.0, Jane=3.0} {4.0=Josh, 2.0=Alex, 3.0=Jane} </code> ===== 21.11 もっと知りたい? Android KTX と Ankoライブラリ ===== [[https://developer.android.com/kotlin/ktx?hl=ja|Android KTX - Android Developers]] [[https://github.com/Kotlin/anko|Kotlin/anko]] ===== 第22章 コルーチン紹介 ===== ==== 22.4 コルーチンを有効にする ==== build.gradle(Module.app) <code> dependencies { ・・・ //implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5' // 古い implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2" // android (async, await) implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2' // launch Deferred ・・・ } </code> ==== 22.5 asyncでコルーチンを指定する ==== CharacterGenerator.kt <code kotlin> //import kotlinx.coroutines.experimental.Deferred //import kotlinx.coroutines.experimental.async // ↓ import kotlinx.coroutines.Deferred import kotlinx.coroutines.async import kotlinx.coroutines.GlobalScope // return async ⇒ GlobalScope.async fun fetchCharacterData(): Deferred<CharacterData> { return GlobalScope.async { val apiData=URL(CHARACTER_DATA_API).readText() CharacterGenerator.fromApiData(apiData) } } fun fromApiData(apiData:String):CharacterData{ val (race,name,dex,wis,str)= apiData.split(",") return CharacterData(name,race,dex,wis,str) } </code> NewCharacterActivity.kt <code kotlin> //import kotlinx.coroutines.experimental.android.UI //import kotlinx.coroutines.experimental.launch // ↓ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch // launch(UI) { ⇒ GlobalScope.launch(Dispatchers.Main) { GlobalScope.launch(Dispatchers.Main) { characterData = CharacterGenerator.fetchCharacterData().await() displayCharacterDate() } </code>
kotlin/kotlinプログラミング.txt
· 最終更新: 2019/12/10 08:10 by
ips
ページ用ツール
文書の表示
以前のリビジョン
バックリンク
文書の先頭へ