Kotlinの基礎をざーっとやってみました。
新しいプログラミング知識として、getter、 setter、アクセス修飾子、ジェネリクス、インターフェース、 null安全 の概念が得られました。
学習メモを下に貼っておきます。
次回はアンドロイドアプリ開発をやっていきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
// Hello Worldを出力する最小限のコード /* fun main(){ print("Hello World!") } */ // 実行は shift+ cntrol + F10 // コメント文 一行 /* コメント文 複数行 コメント コメント */ /* 変数の定義 val 再代入不可 var 再代入可能 */ /* 型 String Char Int Short Long Float Double boolean : true or false 型を付けない場合でも型推論が機能する */ // タブtab : \t // 改行new line : \n // 演算 + - * / % // カウントアップ カウントダウン ++ -- // 代入 // z = z + 5 // z += 5 // 論理演算子 and or not // && || ! fun main(){ val s: String = " This is string" val c: Char = 'a' val i: Int = 100 val f: Float = 123.456f val b: Boolean = false println("$s $c $i $f $b") println("$s \t $c \n $i \t $f \n $b \n") val x = 10 // 型推論を使用 println(x + 3) println(x - 3) println(x * 3) println(x / 3) println(x / 3.0) println(x % 3) var y = 10 println(y++) println(y--) var z = 10 z = z + 10 println(z) z += 10 println(z) val flag= true println(!flag) println(flag || !flag) println(flag && !flag) // 文字と数値の連結 println("hello" + " world") val name = "Mike" println("My name is $name") // My name is Mike val my_age = 20 val your_age = 30 println("私とあなたの年齢を足し算すると ${my_age + your_age} 歳です。") // if文 // 比較演算子 == > >= < <= != val score = 55 if (score > 70) { println("あなたはのスコアは $score です。 合格") }else if (score > 50) { println("あたはのスコアは $score です。不合格です。") }else{ println("もう一度 学習し直しましょう。") } // if文の結果を代入できる val result = if (score > 80) "合格" else "不合格" println(result) // when文 : 他の言語ではswitch文に相当する val dice = 4 when (dice){ 1, 2 -> println("1点") 3, 4 -> println("3点") 5, 6 -> println("5点") in 7..10 -> println(" No way !") else -> println("終了") } // whe文の結果を代入できる val point = when(dice){ 1, 2 -> "1点" 3, 4 -> "3点" 5, 6 -> "5点" else -> "終了" } println(point) // while文 var cnt = 0 // 初期化 while ( cnt < 10){ print("while loop : $cnt \n") cnt++ } // do while文 :後判定なので必ず1回は実行される。 cnt = 0 //初期化 do { println("do_while loop : $cnt") cnt++ }while (cnt < 10) // for文 と if文 continue , break の組み合わせ for (j in 0..10){ if (j == 3){ continue // for文を強制的に次へすすめる・ } if (j == 8){ break // for文を抜ける } println(j) } // 自分で定義した関数を実行する sayHello() sayHelloNameAge("Mike", 20) sayHelloNameAge() val msg = sayHelloReturn() println(msg) val msg_shorty = sayHelloReturnShorty() println(msg_shorty) // クラスのインスタンスを作成してメソドを実行する val user = User() // クラスUserのインスタンスuserが作成された user.sayName() // メソドを実行 user.name = "DJ" // プロパティを書き換えてみる user.sayName() // 書き換わっているか確認 // クラスのインスタンスをコンストラクター引数付きで作成し実行する val user2 = User2("Tony") //コンスとトラクター引数"Tony" println(user2.sayName()) //メソドを実行 // 初期化メソドのあるクラスのインスタンスを作成する。(実行なし) val user3 = User3("Kate") // getter() , setter() の動きを確認する val user4 = User4("aaa") println(user4.team) // getterによって大文字になる BLUE user4.team = "green" // setterによってプロパティが変更される println(user4.team) // GREEN user4.team = "" // 空を入れるとsetterは何もしない。 println(user4.team) // GREEN // スーパークラスを実行する val superclass = SuperClass("Bob") println(superclass.sayGood()) // Good! Bob // スーパークラスを継承したアドミンクラスを実行する val adminclass = AdminClass("Baba") println(adminclass.sayBad()) // Bad !! Baba println(adminclass.sayGood()) // Good! as the override method // クラスの拡張 val NonOpenClass_Ext = NonOpenClass("Sam") println(NonOpenClass_Ext.sayGJ()) // GJ ! Sam println(NonOpenClass_Ext.sayGoodJob()) // [Ext] Good Job ! Sam println(NonOpenClass_Ext.myName) // [Ext] I am Sam on getter // 抽象クラスから作成した具象クラスの動作を確認する val american = American() val japanese = Japanese() american.sayAbst() // Hello japanese.sayAbst() // こんにちは // インターフェースを継承したクラスを実行してみる val user5 = User5() user5.share() // Sharing... user5.getInfo() // Share interface version is 1.1 . // ジェネリクスを使用しない普通のクラスを実行してみる val myinteger = MyInteger() myinteger.getThree(100) // ジェネリクスを使用したクラスを実行してみる <型指定>に注目 val mydata1 = MyData<Int>() mydata1.getThree(200) val mydata2 = MyData<String>() mydata2.getThree("AAA") // data class を使ってみる // まずは使用しない場合 val p1 = Point(3,5) val p2 = Point(3,5) println(p1) // Point@16c0663d println(if (p1 == p2 ) "same" else "different") // different // 値ではなくて、インスタンス番号が渡されているだけ。 // data classを使えば値を渡せる val p3 = Point2(3,5) val p4 = Point2(3,5) println(p3) // Point2(x=3, y=5) println(if (p3 == p4 ) "same" else "different") // same // 少し脱線して、コピーメソド、分解宣言 val p4_copy = p4.copy() val (p4_x, p4_y) = p4 println(p4_copy) // Point2(x=3, y=5) println("$p4_x : $p4_y") // 3 : 5 // Listを使ってみる CollectionList() // Setを使ってみる CollectionSet() // Mapを使ってみる CollectionMap() // .map .filter .forEach を使ってみる MapFilterForeach() // 例外処理 // division(10, 0) // ↑ エラーがでるException in thread "main" java.lang.ArithmeticException: / by zero // 命令文をtry{}の中に入れるて 例外処理をcatchに入れる division(10, 0) // / catch内が実行されました by zero // 自分で定義した例外処理を実行する division2(10, -10) // Minus number is not acceptable! // nullを使ってみる nullTest() } //============================================================ //---- End of main function ---- //============================================================ // 関数を定義する fun sayHello(){ println("Hello!") } // 引数 初期値を定義した関数 fun sayHelloNameAge(name:String = "john", age: Int = 10){ //引数は型宣言が必要 println("Hello $name . I am $age years-old.") } // 返り値がある関数を定義する fun sayHelloReturn(): String { // returnする値の型宣言が必要 return "Hello! as return" } // 返り値しかない関数は省略して書くことができる : 型が自明なので宣言不要 fun sayHelloReturnShorty() = "Hello! as return on shorty code" // クラスを定義する // クラスのメンバー // data: プロパティ // fun : メソド class User { // プロパティを定義する var name = "Me" // メソドを定義する fun sayName() { // println("My name is ${this.name}") // nameは自明なのでthis.は無くても良い println("My name is $name") } } // コンストラクター引数のあるクラスを定義する class User2(var name: String) { // () はコンストラクタ引数。ない場合は()も不要 // プロパティを定義する // var name = "Me" // コンストラクタ引数がある場合は この行は不要 // メソドを定義する fun sayName() { // println("My name is ${this.name}") // nameは自明なのでthis.は無くても良い println("My name is $name") } } // 初期化メソドのあるクラスを定義する class User3(var name: String) { //初期化メソドを定義する init{ println("クラスのインスタンスを作成し、初期化メソドが実行されました。") } } // Kotlinではgetterとsetterによってプロパティを呼び出されている。 // クラス内で定義したvar変数はgetter, setterを書かなくても自動的に返していた。 // 今回はgetterとsetterをちゃんと定義してみる。(追加機能として大文字で返すようにした。) class User4(var name: String) { var team = "blue" // ここで宣言すると自動的にgetterとsetterが定義されていた。 // getter : 大文字にして返すようにする。 get(){ // get()内で変数はfieldと表現される。(特殊) return field.toUpperCase() } // setter 慣習的に引数はvalueと書く set(value){ //空文字でない場合だけ機能させること if (value != ""){ // getterと同様に var変数はfieldと表現される。 field = value } } // メソドを定義する fun sayName() { println("My name is $name") } } // クラスの継承 : 元クラスの機能を拡張して新しいクラスを作成する // SuperClass : 親クラス(元となるクラス) // AdminClass : 子クラス(機能を追加したクラス) // 上書きするメソドにはoverrideとつけなければならない。 class AdminClass(name: String): SuperClass(name){ fun sayBad(){ println("Bad !! $name") } override fun sayGood(){ println("Good! as the override method") } } // 継承しても良い! という意味で子クラスにはopenを頭につけなければならない // 上書きしても良いメソドにはopenをつけなければならない。 open class SuperClass(var name: String){ open fun sayGood(){ println("Good! $name") } } // アクセス修飾子:アクセスをコントロールする // public : どこからでもアクセス可能 メインクラス そのクラス サブクラス(子クラス) // protected : そのクラス + サブクラス // private : そのクラス // 例) メインからnemeを使えなくする方法 // open class SuperClass(protedted var name: String){ // 例) そのクラス内でしかnameを使えなくする方法 // open class SuperClass(private var name: String){ // クラスの拡張: クラスを継承したいがsuperClassがopenになっていない時、どうやって機能を追加するか。 // 元クラス class NonOpenClass(var name: String){ fun sayGJ() { println("GJ ! $name") } } // メソドを拡張: 機能追加 fun NonOpenClass.sayGoodJob(){ println("[Ext] Good Job ! $name") } // プロパティを拡張 val NonOpenClass.myName: String get() = "[Ext] I am $name on getter" // メソドの上書き(実験) = だめ、元クラスが優先される。 fun NonOpenClass.sayGJ(){ println("[Ext] GJ ! $name") } // 抽象クラス:他のクラスに継承してもらう前提で作られるクラス // 具象クラス:抽象クラスを継承する新しいクラス // 使い方:開発規模が大きいとき、具象クラスの共通メソドを // 一旦抽象クラスのメソドとしてまとめておいて、 // 実装は具象クラスに任せるということをする。 // 抽象クラス abstract class AbstClass{ abstract fun sayAbst() } // 具象クラス1 class Japanese: AbstClass(){ override fun sayAbst() { println("こんにちは") } } // 具象クラス2 class American: AbstClass(){ override fun sayAbst() { println("Hello") } } // Interface : クラスの機能を拡張する // interfaceの中では抽象プロパティ、抽象メソドでもabstractを書く必要がない。 // 継承と違って、クラスにいくつでも実装できる。 interface Sharable{ //抽象プロパティ val version: Double //具象クラスで実装するので、ここでは型だけを定義すれば良い //抽象メソド fun share() //具象クラスで実装するので、メソド名だけ定義しておけば良い //普通のメソド fun getInfo(){ print("Share interface version is $version .") } } // Interfaceを継承する class User5: Sharable{ override val version = 1.1 override fun share() { println("Sharing...") } } // ジェネリクス // まずはジェネリクスを使用しない例 class MyInteger{ // プロパティを3回出力するメソド fun getThree(x: Int){ println(x) println(x) println(x) } } // これでは、IntではなくStringを入れたい場合に書き換えなければならない。 // ジェネリクスを使用して型を汎用化できる class MyData<T>{ // <>内は何でも良いが、慣習的にタイプの意味でTとしている。 // 実行時に具体的なタイプを入れればOK fun getThree(x: T){ // タイプをコンストラクタと同じTにする。 println(x) println(x) println(x) } } // data classを使ってみる // 使わない場合 class Point(val x: Int, val y: Int){ } // これではインスタンスに引数が渡されないので // mainで動かしているp1はインスタンス番号 p1==p2はインスタンスう番号が違う、 // という結果にしかならない。 // data classで解消する data class Point2(val x: Int, val y: Int){ } // Collection : データの集合 // List 順番がある配列 // Set 順番がなく重複がない集合 // Map キーとバリューで管理していく集合 // Immutable 変更可能 // Mutable 変更不可 fun CollectionList(){ // listOfは型変更不可Immutable // 変更したい場合はmutableListOf<>()を使用すること val li: List<Int> = listOf(1, 2, 3, 4, 5) // 型推定も有効 println(li[3]) // 4 println(li.size) // 5 for (element in li){ println(element) // 1 2 3 4 5 } } fun CollectionSet(){ // setOf : 書き換え可能にしたい場合は mutableSet<>()を使用すること val se: Set<Int> = setOf(1,2,2,2,3) // 重複している2は無視される println(se) // [1, 2, 3] // 要素が含まれているか調べる println(se.contains(3)) // true // 積集合 和集合 差集合 val se1 = setOf(1,3,5,7) val se2 = setOf(3,5,8,9) println(se1.intersect(se2)) // 積集合 [3, 5] println(se1.union(se2)) // 和集合 [1, 3, 5, 7, 8, 9] println(se1.subtract(se2)) // 差集合 [1, 7] } fun CollectionMap(){ // MapOf : 書き換え可能にしたい場合は mutableMapOf<,>()を使用すること val users6: Map<String, Int> = mapOf("a" to 10, "b" to 20, "c" to 30) println(users6) // {a=10, b=20, c=30} println(users6.size) // 3 println(users6.keys) // [a, b, c] println(users6.values) // [10, 20, 30] println(users6.entries) // [a=10, b=20, c=30] println(users6["b"]) //20 } // リスト内の要素を操作するmap 抽出するfilter 出力するforeach fun MapFilterForeach(){ val values = listOf(12.3, 45.6, 78.9) values // valuesに10%のVATを追加して出力する //.map {n -> n * 1.10} // 適当な引数n -> 処理 // itを使うと引数nを省略できる .map { it * 1.10 } // filterを使って抽出する .filter { it > 20 } // foreachで出力する .forEach { println(it) } } // 例外処理try cahtch : Kotlinに予め設定されている fun division(a: Int, b: Int){ try { println(a / b) } catch (e: ArithmeticException) {// 予めKotlinが用意している例外名 println("catch内が実行されました") println(e.message) // 予めKotlinが用意している例外プロパティ } } // 独自の例外処理を定義する try if throw catch / Throwable(message) fun division2(a: Int, b: Int){ try{ // 例外処理を実行する条件 if (b<0) { // 例外処理を実行する throw MyException("Minus number is not acceptable!") } // catchしたい例外処理を定義して、catchしたときの処理を実行する } catch (e: MyException) { println(e.message) } } // Throwableという予めKotlinが用意してあるクラスを継承する. // コンストラクタ引数として例外プロパティmessageを入れる class MyException(message: String): Throwable(message) // Null 安全 : Nullable型を使用してみる fun nullTest(){ // あるデータがnullかどうか曖昧だと重大なバグが発生する可能性が高い。 // どうしてもnullを使いたい場合は nullableという特殊な型指定 ? が必要 // val s: String = null // これはエラーになる val s: String? = null println(s) // ちゃんとnullになった // nallableな変数は後々 nullかどうかチェックしながら使用すること if (s != null){ // nullでないときだけ実行する println(s.length) }else{ println("Variable is null.") // Variable is null. } // もっと簡単にnullチェックして使用する方法 println(s?.length) // nullなので実行されない // エルビスプレスリー演算子?:を使用して, nullだったら -1を返す println(s?.length ?: -1) // -1 // nullだったら例外を発生させる // print(s!!.length) //Exception in thread "main" kotlin.KotlinNullPointerException } |