見出し画像

「COMPOSE を用いた ANDROID アプリ開発の基礎」の学習支援⑥ -ユニット2パスウェイ1

皆さん、こんにちは!又はこんばんは!初めての方は初めまして!
Google Codelabsの「COMPOSE を用いた ANDROID アプリ開発の基礎」コースのお手伝いをする「りおん」です。

「COMPOSE を用いた ANDROID アプリ開発の基礎」コースの補足について書きます。
今回は、ユニット2「アプリ UI を作成する」の中のパスウェイ1「Kotlin の基礎」です。

補足なので、「COMPOSE を用いた ANDROID アプリ開発の基礎」コースで心配になった時、エラーが起きて詰まった時や、分からないことがあった時に見てください!
また、目次を見て、自分に必要なところだけ見るのをお勧めします!


最初に

Codelabsの受講お疲れさまでした!
今回のコースは学習内容が非常に抽象的かつ量が膨大だったため非常に大変だったと思います。
「ほとんど理解できなかった…」という方も安心してください!今回の内容を理解できる人はKotlinの学習がある程度終わっている人です。今後は今回習った内容がもっと具体的な形で出てくるのでそこでわかるようになれば大丈夫です!

学習内容

下の4つが今回の主題でした。
1.条件の使用法
2.nullの使用法
3.クラスとオブジェクト
4.ラムダ式

1.条件の使用法

条件文として、if/else文とwhen文がありました。
どちらでも「~なら・・・」という条件が複数あっても表現できますが、条件が3個以上の場合はwhen文を使った方が見やすいことも分かったと思います。
また、when文で「または」を使いたい場合は“,(カンマ)”、「~の中にあるなら」なら"in + (範囲)"、データ型を確認する時は"is"を用いることも学び、そして最後に更なる短縮法として条件を式に用いる条件式を学んだと思います。
下のコードはどれも同じ条件文ですが、上からif/elseで書いたもの、whenで書いたもの、whenの条件式を使ったものとなっています。比較すると下に行くほど文字数が少なくなり読みやすくなっています

fun main() {
    val x = 20

    if (x == 2 || x == 3 || x == 5 || x == 7) {
        println("x is a prime number between 1 and 10.")
    } else if(x in 1..10){
        println("x is a number between 1 and 10, but not a prime number.")
    }else if(x is Int){
        println("x is an integer number, but not between 1 and 10.")
    }else {
        println("x isn't an integer number")
    }

}
fun main() {
    val x = 20

    when (x) {
        2, 3, 5, 7 -> println("x is a prime number between 1 and 10.")
        in 1..10 -> println("x is a number between 1 and 10, but not a prime number.")
        is Int -> println("x is an integer number, but not between 1 and 10.")
        else -> println("x isn't an integer number.")
    }
}
fun main() {
    val x = 20

    val message = when (x) {
        2, 3, 5, 7 -> "x is a prime number between 1 and 10."
        in 1..10 -> "x is a number between 1 and 10, but not a prime number."
        is Int -> "x is an integer number, but not between 1 and 10."
        else -> "x isn't an integer number."
    }
    
    println(message)
}


2.nullの使用法

次にnullについて学んだと思います。
nullとは変数に値がないという状態を表すものでした。
Int?やString?の様にデータ型の後に?を付けることで変数をnull 値許容型として定義できること、null値許容型変数のメソッドやプロパティにアクセスするための方法(?.と!!.)も学んだと思います。

3.クラスとオブジェクト

その後は、クラスとオブジェクトを使用する方法として、クラスの定義からオブジェクトをインスタンスする方法まで学んだと思います。ここが今回一の難所だったと思います。

その為、クラス、プロパティ、メソッド、コンストラクタ、オブジェクトの関係についてまとめます。
クラスは3つの要素で構成されており、それがプロパティ、メソッド、コンストラクタです。
プロパティはクラスの中にある変数つまりはデータ。
メソッドはそのクラスが持つ機能。
コンストラクタはクラスがインスタンス化する時に実行されるコードです。
クラスは設計図なのでそのままでは価値がありません。そこでインスタンス化しオブジェクトという物になります。

これらをスマホに例えると、スマホの設計書があります。そこには、スマホは機種名、製造ナンバー(id)というプロパティを持っており、機能としてはカメラ、電話、メールがあり、そして製造される時に製造ナンバーを付けるというコンストラクタが書かれています。そして、この設計書を基に作った(インスタンス化した)ものがスマホ(オブジェクト)なのです。

また、クラス間の関係という項で親クラス(=スーパークラス)と子クラス(=サブクラス)というIS-A関係と、そのクラスを持っているというHAS-Aの関係について学習したと思います。両者とも同じコードを二回も書かなくていい(=コードの再利用できる)ように使用します。
そこも複雑ですので解説します。

IS-Aの関係の親クラスと子クラスの具体例をいうと、親クラスは哺乳類で子クラスはヒトと猫と考えてください。
ヒトと猫のクラスを作るとします。
恒温動物であること、胎生であること、脊椎動物であること等々同じ特徴が見つかります。同じ文を記述するのはとても手間ですし、もしエラーが起きたら修正する箇所が二倍に増えたりと悪いことだらけです。そこで共通点となる哺乳類というのに纏めるというのが親クラスと子クラスの関係です。

同じ項目を何度も書く必要がある
上と比べて行数が少ない

HAS-Aというのは家の中にスマートテレビがあると例えられたように両者に性質が類似しているというような関係はなく、ヒトがスマホを持つといったまさにHASの関係です。

4.ラムダ式

ラムダ式について学びました。
ラムダ式は中カッコ{ }で囲われたコードです。このラムダ式を用いることで、コードを短くすることが出来ます。以下のコードは全て同じ機能を持ちますが、ラムダ式を使った方が短いことが分かると思います。

fun main() {
    println(sum1(10,20))
    println(sum2(10,20))
    println(sum3(10,20))
}

val sum1: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

val sum2 = { x: Int, y: Int -> x + y }

fun sum3(x: Int, y: Int):Int{
    val y = x + y
    return y
}

また、ラムダ式を関数に渡す手法を学びましたがこれも以下のコードを見ればわかるようにvalから始まる一文が省略できており、短くまとまっていることが分かります。

fun main() {
    //ラムダ式を関数に直接渡す
    println(average(10,20,{x: Int, y: Int -> x + y}))
    //上と同じだが、sum1を定義する必要がある
    println(average(10,20,sum1))
}

//ラムダ式
val sum1: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

fun average(x: Int, y: Int, sum: ((Int, Int) -> Int)):Int{
    return sum(x, y) / 2
}

用語整理

下の用語は知っていると今後がより楽になると思われるものをピックアップしたものです。

ブール式

「②Kotlin で条件を記述する」内の「if / else ステートメントを使用して条件を表す」に出てきた言葉です。
ブール式とは条件式のことで、結果が必ずtrue又はfalseになる式のことです。

ステートメント

「②Kotlin で条件を記述する」内の「if / else ステートメントを使用して条件を表す」に出てきた言葉です。
IT用語辞典によると、ステートメントとは一つ一つの手続きや命令、宣言などのことと説明されています。
なので、文章中に「ifステートメント」と出てきたら「if文」と訳すとわかりやすいです。

コンパイル

「②Kotlin で条件を記述する」内の「if / else ステートメントを使用して条件を表す」に出てきた言葉です。
Kotlinのような人でも読める高級言語から、機械語(0,1のみ)というコンピュータが読める言語に変換することを言います。
人がプログラムを書く->コンパイルする -> コンピュータで実行されるの順です。

null安全

「③Kotlin で null 可能性を使用する」内の「null 値許容変数の扱い方」に出てきた言葉です。
値がないものの値を取ろうとするとアプリがクラッシュします。なにせ値がないのですから。(このエラーをNullPointerExceptionと言います)
null安全とは、null参照をする可能性を減らすための工夫で、要は「疑わしきは罰せよ」の精神です。コンパイルの際に、null参照の可能性があるコードを見つけた瞬間にエラーを出してくれます

アサート/アサーション

「③Kotlin で null 可能性を使用する」内の「null 値許容変数の扱い方」に出てきた言葉です。
アサ―トは動詞、アサーションが名詞です。意味は「表明する」、「断言する」というもので、非 null アサーションという言葉は「絶対にnulではない!!!」という宣言です。

オブジェクト指向プログラミング(OOP)

「④Kotlin でクラスとオブジェクトを使用する」内の「はじめに」に出てきた言葉です。
IT用語辞典によると、関連するデータの集合体と、それを操作する手続きを「オブジェクト」(object)と呼ばれるひとまとまりの単位として一体化し、オブジェクトの組み合わせとしてプログラムを記述する手法。と説明されています。
今回学んだ内容で訳すと、関連するデータの集合体(->プロパティ)と、それを操作する手続き(->メソッド、コンストラクタ)を「クラス」に一纏めして、クラスをインスタンス化したオブジェクトの組み合わせとしてプログラムを記述する手法。となります。
OOPという分類にKotlinは含まれているという認識で大丈夫です。
大事なのは、カプセル化、抽象化、継承、ポリモーフィズムという4つの特徴です。これらも学習する中で次第にわかっていくので今理解する必要があるわけではありません。

カプセル化

プロパティと、メソッドをクラスという形でひとまとまりにすることです。そうすることにより、可視性を用いることでクラス外からのプロパティやメソッドのアクセスを制限できます。

抽象化

Codelabsでは、カプセル化の延長で、内部の実装ロジックを可能な限り隠すという考え方と書かれていました。よく言われる抽象的と同じで、具体的な部分は隠して、本質のみ取り出すということ。もっと具体的に言うと子クラスから親クラスは抽象化という感じです。

継承

親子関係(親クラス、子クラス)をつくることで、親クラスから子クラスへ特性(プロパティやメソッド)をコピーすることです。

ポリモーフィズム

Codelabsでは、ポリモーフィズムとは、異なるオブジェクトを単一かつ共通の方法で使用することを指します。と説明されていました。
具体的に言うと、同じ親クラスを持つ子クラスは同じ名前のメソッドを持っていますが、このメソッドは子クラスごとに違う働きを持てることです。
Codelabsでもありましたが、下がポリモーフィズムの例です。子クラスは同名だが昨日の違うturn on()とturn off()メソッドを持っています。

fun main(){
    var smartDevice: SmartDevice = SmartTvDevice("Android TV", "Entertainment")
    smartDevice.turnOn()

    smartDevice = SmartLightDevice("Google Light", "Utility")
    smartDevice.turnOn()
}

open class SmartDevice(val name: String, val category: String) {
    var deviceStatus = "online"

    open fun turnOn() {}

    open fun turnOff() {}
}

class SmartLightDevice(deviceName: String, deviceCategory: String) :
    SmartDevice(name = deviceName, category = deviceCategory) {

    var brightnessLevel = 0
        
    override fun turnOn() {
        deviceStatus = "on"
        brightnessLevel = 2
        println("$name turned on. The brightness level is $brightnessLevel.")
    }

    override fun turnOff() {
        deviceStatus = "off"
        brightnessLevel = 0
        println("Smart Light turned off")
    }
    }

class SmartTvDevice(deviceName: String, deviceCategory: String) :
    SmartDevice(name = deviceName, category = deviceCategory) {

    var speakerVolume = 2
    var channelNumber = 1
        
    override fun turnOn() {
        deviceStatus = "on"
        println(
            "$name is turned on. Speaker volume is set to $speakerVolume and channel number is " +
                "set to $channelNumber."
        )
    }

    override fun turnOff() {
        deviceStatus = "off"
        println("$name turned off")
    }
}

セカンダリコンストラクタ

複数のコンストラクタが必要になった時に用います。複数のコンストラクタを用いるため、複雑な初期化処理を行うことが出来ます。
過去のCodelabsではほぼ見なかったので、こんなのもある程度で大丈夫ですし、constructor()とデカデカと書かれているのですぐに分かります。

その他の注意点

アクティビティの残数が減らない

よくあります。
コースを受講してテストに合格しバッジを貰ったなら、無視して構いません。

最後に

今回の内容は、質と量ともに重かったので学習するのに骨が折れたと思います。
初めて習った方は、今回の内容が理解できなかったという方が大半だと思いますが理解するまで読むのではなくコースを進めることをお勧めします!概念というのはその具体例を知らないと中々理解できませんし、何より楽しく学ぶためにも先に進むべきです!
次の講座からは遂にAndroid Studioでアプリを作っていきます!今よりもっと楽しいことが待っているので是非Codelabsを引き続き学習してください!

最後の最後に

本記事を読んでいただきありがとうございました。
前回から約一か月ほど更新に時間がかかり、お待ちしていくれた方には大変申し訳ございません。今後は、毎週火曜に更新していく予定ですのでよろしくお願いします!



この記事が気に入ったらサポートをしてみませんか?