2019年6月にやったこと

引き続きSpring Security・OAuth2.0、OIDCあたりをごにょごにょしていた。 中国語がだれている。というか全体的にだれていた。

英語

English Bellを23レッスン受講した。 かなりダレてきたのでプランを軽いやつに変更した。 代わりに福利厚生でレアジョブができるようになったのでちょっとやってみている。

5月に受けたTOEICはR400、L350の750だった。受けるたびにReadingのスコアが伸びているが、それ以上にListningのスコアが落ちるので合計がどんどん下がっている。 なんで英会話しかやってないのにこうなるのか不思議だ。 あとは文法が全然ダメでPart7が9割くらい正解している人になっているので、文法をいい感じにするとRは450くらいを目指せる気がしている。Lはもうわからん。

OAuth徹底入門 セキュアな認可システムを適用するための原則と実践

token endpointにredirect_urlを送る理由とか、stateパラメータの存在意義とかがいまいちわからず、うーん???となっている。 あとはhttps://openid.net/specs/openid-connect-session-1_0.htmlを読んだりしていた。

情熱プログラマー

なんか気づいたら読み終わってた。

その他

Treviewの改修したりしてた。 https://github.com/inabajunmr/treview

これからやること

2019年5月にやったこと

Androidアプリがらみの資料とかみてた。 業務ではSpring SecurityとOAuth 2.0関連をごにょごにょしてた。あとDynamoDBとか。Spring Securityはフィルター。

Release It! 本番用ソフトウェア製品の設計とデプロイのために

読み終わった。Resilience4jで遊ぶ的なことを考えている。

英語

English Bellを39レッスン受講した。ステージ8がはじまった。 TOEICを受けたので直前にhttps://www.amazon.co.jp/dp/4023304603/を読んだ。 TOEICはRはまあまあでLが死んだ。結果は6月半ば。あとiKnowをサボってたのでちょこちょこやってた。

中国語

https://www.amazon.co.jp/dp/4863922191を読んでたが停滞している。四声が覚えられないストレスがやばい。 https://www.udemy.com/chinese-made-easy これを半分くらい見た。発音については本よりもレッスンのがいい。 本だと同じ音声をループするのがつらい。

6/23に中国語検定の準4級と4級を受けるが間に合うのか。

Kotlinのリファレンス読む

コルーチン以外の部分をざっくり読んだ。とりあえず一旦終わりにしてコードを書く。

OAuth徹底入門 セキュアな認可システムを適用するための原則と実践

ちまちま読んでる。OAuth2.0の各認可フローはだいたい頭に入ってるのでそのあたりはサクサク読んでる。

Android 入門読んだ

ざっくりわーっと動かしながら読んだ。 http://inabajunmr.hatenablog.com/entry/2019/05/05/182705

あとはサンプルアプリ眺めてなんとなく雰囲気を掴んだりした。 http://inabajunmr.hatenablog.com/entry/2019/05/06/135147

スマホアプリの設計を雑にしたのでコードを書いていく。

Clean Architecture 達人に学ぶソフトウェアの構造と設計

なんとなく読み始めた。オブジェクト指向ってなあに?についてはいままでで一番納得感がある。まだ本番に入ってない感じ。さっと読みたい。

これからやること

  • 読書会プラットフォーム作る
  • プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
    • 読む
  • ElectronかWebアプリ(サーバなし)でNature RemoのPC用クライアントを作る
    • なぜか俺は音声やスマホよりもPCで操作したい時がたまにある
      • あとはSPAとJSの学習用に
        • 読書会プラットフォームの後
  • Goならわかるシステムプログラミング
  • Kotlinがらみなんか
    • Kotlinインアクションとか
  • 英語
  • 中国語
  • ここ最近ほとんど業務でプログラミングをしなくなって、調整とかレビューとかばっかしてるがかなり雰囲気でやってるので、マネジメント系の本を読もうとしている
    • なにがいいのかよくわからん
  • Effective Go - The Go Programming Language
  • パタヘネ
  • スマホアプリ作る

Android Architecture Components Basic Sampleを眺める

なんとなくAndroidアプリ作れそうな空気は感じたけどどういう構造にするのが一般的なのか知りたかったのでこれを眺めている。

github.com

root

BasicAppがApplicationを実装しててこいつ経由でリポジトリとってこれるようになってる

db

  • DataGenerator
    • fixture的なやつ

converter

Utility的な

dao

Dao。 LiveDataで受けるようにすると、データの変更に対してXXXを発火、みたいなことができる

entity

Entity。

model

なんかデータのフィールドを持ってるinterface。entityが背負っている。 entityをmodelの層で使うぜ的なあれ?

ui

Activityがここにいる MainActivityのonCreateの引数のBundleてなんだろ

https://qiita.com/yyyske/items/c6e342a9008bebef75bd

Activityが死ぬとここになんか入ってくるらしい

Activityが破棄されたあとの復元時に必要なデータをbundleに突っ込んどいてonCreateでbundleがnullの時に復元すると良いらしい

が、このサンプルではそういうことをしてる感じがしないのでよくわからん

Adaptor

Flagmentでモデルに変更が入るとAdaptorに変更後のデータをセットする感じ RecyclerView.Adapterは多分RecyclerViewに値をバインドするのをやっている

Viewmodel

  • ViewModelがいる
  • ViewModelのファクトリが初期化されるタイミングでApplicationからリポジトリを取得してる
  • ViewModel自体はリポジトリとApplicationを受け取って初期化時に必要なデータを取ってきてる

ということはViewModelそのものは 画面に表示するためのデータを取ってきて保持するやつ という理解でいいのかな

ViewModelはFlagmentのonActivityCreatedで生成している。 https://github.com/googlesamples/android-architecture-components/blob/17c315a050745c61ae8e79000bc0251305bd148b/BasicSample/app/src/main/java/com/example/android/persistence/ui/ProductFragment.java#L68

onActivityCreatedはFlagmentが呼び出されたActivityのonCreateで呼ばれる http://sakura-bird1.hatenablog.com/entry/20111207/1323267262

その他

fragmentってなんだ https://qiita.com/Reyurnible/items/dffd70144da213e1208b Activityの画面の中に表示される一要素って感じ

ざっくり流れとしての理解

  1. MainActivityが呼び出されると、Fragmentを生成して画面要素にFragmentを追加?
    1. https://github.com/googlesamples/android-architecture-components/blob/17c315a050745c61ae8e79000bc0251305bd148b/BasicSample/app/src/main/java/com/example/android/persistence/ui/MainActivity.java#L34
    2. 画面側としてはFragmentのコンテナだけ用意しとく感じ
  2. FragmentのonCreateViewが呼ばれて、レイアウトが設定される
  3. FragmentのonActivityCreatedが呼ばれる
    1. ViewModelProviders経由でViewModelを生成する(ViewModelProvidersはViewModelのライフサイクルを管理してくれるらしい)
    2. subscribeToModelでモデルをサブスクライブする
  4. Daoからデータを変更すると、LiveDataで取得したデータについてオブザーブしている部分が発火する
  5. 変更後のデータをアダプター経由でViewに伝える

大体こんな雰囲気だと理解した

Android 入門を読んでいる

Android 入門を読んでいる

使ってた筋トレ記録アプリが突如としてサービスを終了し、他にしっくり作るアプリが見つからなかったのでとにかく単純なログアプリを作ろうとしている。 ので、とりあえずAndroid入門を読んでいる。

てきとう

  • Activity:単位がよくわからない。今の所1画面1アクティビティだけど説明見た感じそういう事でもなさそう
    • ユーザがなんかする1単位?  * 画面でいいらしい
  • AndroidManifest.xml
    • Chrome extensionのマニフェストみたいな
    • アイコンとかどういう画面あってどういう関係か、とかを定義
    • 呼べるAPIの制限とか
      • カメラ使えるかどうかとか
  • ViewGroupはViewを束ねたやつ
    • レイアウト、という感覚で良さそう
    • Viewはレイアウト内の要素
  • UIはXMLで定義する
  • テキストはstrings.xmlに定義してUIのXMLで設定する
  • リソースはR.xxx(package).xxx(id)で参照できる
    • なんでだ

ボタン押してどうこう

Activity内にメソッド定義(引数がViewで、戻り値なし)して、これをView側のonClick属性に設定すると押したタイミングでメソッドがコールされる。

IntentはコンポーネントをバインドしてXXXする、みたいなのを表現する何かっぽいが感覚がわからん。Activity内のメソッドから別のActivityをセットしたIntentを用意してstartAcitivity()するとActivityから別のActivityを起動できる感じ。 Intent経由でActivity間のメッセージ送信もできる。起動した後のActivityでもIntentを参照できるっぽい。同じインスタンスなのかよくわからん。

Android StudioでActivity作るときはNew > Activity > Empty Activityで作るとレイアウトファイル作ってマニフェストにActivityをセットして、までをまとめてやってくれる。

コンポーネント

https://developer.android.com/guide/components/fundamentals?hl=ja

  • Activity
    • 画面
  • Service
    • バックグラウンドで動くやつ
    • 再生中の曲とか
  • ContentProvider
    • なんか永続化するやつとか
    • あんまわからん
    • ActivityからSQLite呼ぶ的なあれとは違うのか
    • ガイドにSQLiteがどうこうって書いてあるけどSQLiteデファクトスタンダート的なあれなのだろうか
  • BroadcastReceiver
    • なんかイベントハンドラ的なやつ?
    • 電池きれそうになったらXXXX!とかなんかダウンロード終わったら通知みたいな
    • 状況に関わらずなんか起きたらなんかする、みたいな感じ?

別のアプリのアクティビティも起動できるらしい。自分で開発したアプリからデフォルトのカメラアプリを起動するとか。プロセスは別になる。 なので、Androidアプリのエントリポイントは複数あって、main()ではない。いわゆるアプリ起動時のエントリポイントはマニフェストで定義する。

なんとなく雰囲気的には

アクティビティからインテントを定義して別のコンポーネントをコール→コンポーネントが起動する。インテントでゴニョゴニョする→元のアクティビティに戻したければ戻す。インテントを介してデータを戻したりもできる

みたいな感じが基本的な流れなんだろうか

コンテンツプロバイダ

https://developer.android.com/guide/topics/providers/content-provider-basics?hl=JA

そもそもなんなのかがわからん 永続化のための抽象的なレイヤーなのかなと思ってるが

なのでチュートリアルを見ている https://developer.android.com/guide/topics/providers/content-provider-creating

と思ったけど単純にローカルのSQLite使いたいだけならRoomな感じがするな

Room

https://developer.android.com/training/data-storage/room

we highly recommend using Room instead of SQLite はい

DatabaseクラスからDaoを取ってきてDao経由でEntityを取得したり永続化したりする感じだ

適当なボタンのonClickからデータを登録したりなんだりしたらこうなった

Caused by: java.lang.RuntimeException: cannot find implementation for com.example.myfirstapp.model.AppDatabase. AppDatabase_Impl does not exist

https://stackoverflow.com/questions/46665621/android-room-persistent-appdatabase-impl-does-not-existの回答に従ってbuild.gradleをいじると

Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

になった。

https://qiita.com/toastkidjp/items/49ad3035a6df525ce040 ほーーん???

ほーーん?????

ボタン押すとデータ取ってきて画面に表示、みたいのはどう実装するのが良いのか

安直にAsyncTaskで全部やるようにしたら元のスレッドからしかビューをいじれんぞと怒られる

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

DB触るだけならこれで良さそうだけど画面に表示して云々はこれだとダメそう

DB触るの重い処理だからバックグラウンドでやろうぜ、はわかるようなわからないような感じなんだけど(SPAでAPI叩くのと同じノリだと思っている)、紙芝居形式のアプリでそこ頑張るメリットがよくわからなかったのでとりあえずallowMainThreadQueriesでいいやとなってしまった 初期化はどのタイミングでするのが良いのだろうか あとはマイグレーションどうするとかかなーその辺解決したらとりあえず作り始めて良さそうだ

qiita.com

なんかこのチュートリアルが良さそう

Android Room with a View - Kotlin

リポジトリがDao持ってて、ViewModelインスタンスの初期化時にリポジトリ初期化してあとはViewModelがリポジトリ持ってる感じだった これActivityでも同じ事していいんだろうか というかViewModelがなんなのかよくわかってない

qiita.com

なんかいい感じのサイズのサンプルアプリケーションとかないかな

サンプルを眺める

github.com

良さげだ

2019年4月にやったこと

なんかKotlinのリファレンスとか見てた

Release It! 本番用ソフトウェア製品の設計とデプロイのために

17章くらいまでみた。読み終わったらどうしようかな的なことを考えている。サーキットブレーカーで遊ぶ会みたいなのやったら良いだろうか。

英語

English Bellを42レッスン受講した。ゴールデンウィークはサボっていた。ステージ7の途中まで行った。

中国語

https://www.amazon.co.jp/dp/4863922191をひたすら読んでた。

若干掴めてきた感じはある。6/23に中国語検定の準4級と4級を受けてみる。

速習 Kotlin: Javaより簡単!新Android開発言語を今すぐマスター 速習シリーズ

ざらざらっと読んだ。公式のリファレンスだけでも良さそうではあったけどサクッと読めたのでよかった。

Kotlinのリファレンス読む

読んでる

http://inabajunmr.hatenablog.com/

どこまで読むか悩んでるんだけどOtherが結構重要そうなんだよな Core Librariesとかも読みたい

OAuth徹底入門 セキュアな認可システムを適用するための原則と実践

Kindleでセールやってたので勢いで買ってしまった。電車とかで読んでる。多分release it読み終わってから真面目に読む

これからやること

  • 読書会プラットフォーム作る
  • プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
    • 読む
  • ElectronかWebアプリ(サーバなし)でNature RemoのPC用クライアントを作る
    • なぜか俺は音声やスマホよりもPCで操作したい時がたまにある
      • あとはSPAとJSの学習用に
        • 読書会プラットフォームの後
  • Goならわかるシステムプログラミング
  • Kotlinがらみなんか
    • Kotlinインアクションとか
  • 英語
  • 中国語
  • Release It!
  • ここ最近ほとんど業務でプログラミングをしなくなって、調整とかレビューとかばっかしてるがかなり雰囲気でやってるので、マネジメント系の本を読もうとしている
    • なにがいいのかよくわからん
  • Effective Go - The Go Programming Language
  • パタヘネ

Kotlinのリファレンスを読んでいるメモ

Kotlinのリファレンスを読んでいる

kotlinlang.org

諸事情でKotlinを覚えるかとなったので

速習 Kotlin: Javaより簡単!新Android開発言語を今すぐマスター 速習シリーズ

速習 Kotlin: Javaより簡単!新Android開発言語を今すぐマスター 速習シリーズ

とりあえずこれをざっと読んだけど結局リファレンスを読んでいる この本はJavaわかれば電車とかでびゃっと読めてなんとなくKotlinかけるようになると思うのでやる気あんまないけどざっくり把握したいみたいな時には良さそう try式ないとかあったのでなんとなく書くレベルで必要なのが網羅できてるかというとなんとも言えない

やる気があるならリファレンス読めば良さそう だいたいのことがそう

どこまで読んだか忘れちゃうのでメモレベルのメモ

Control Flow: if, when, for, while

  • ifが式なので三項演算子ない
  • if式はelseないとだめ
  • when(switchみたいの)もそう
  • 引数なしwhenはif-else ifのノリで使える
    • else ifだらけになる場合こっちのが良さそう

Returns and Jumps

  • ラムダ式のなかでreturnするとラムダ式を書いた関数からreturnされちゃう
    • ラムダ式だけをreturnしたい場合はラベルで頑張る
    • 匿名関数で書けば匿名関数だけreturnできる
    • こはちょっと微妙な気持ちなったけどラベルガンガン使ってく文化なのかな

Classes and Inheritance

  • プライマリコンストラクタはbodyを持てないので、initブロックで初期化処理を書く
  • initブロックは複数かける。書いた順に実行される
  • initブロックではプライマリコンストラクタの引数を参照できる
  • プライマリコンストラクタの引数はクラスのフィールドになる
    • valで宣言した引数はread-onlyなフィールドになる
fun main() {
    var test = Test("test")
    println(test.value)
}

class Test(var value:String){
    init {
        println("You can read property defining at Primary Constructor. $value")
    }

    init {
        println("You can define multiple initializer")
    }
}
  • 全てのinitializerはセカンダリコンストラクタよりも前に実行される
  • プライマリコンストラクタがないとデフォルトコンストラクタを生成される。デフォルトコンストラクタを露出せずプライマリコンストラクタを定義したくない場合、引数なしでprivateなプライマリコンストラクタを定義する
  • プライマリコンストラクタの引数が全てデフォルトを持っていると、JVM上ではそのデフォルトを使う引数なしコンストラクタを生成する
  • 全てのクラスはAnyを継承している
  • 継承する場合は継承元のコンストラクタで初期化してあげること
open class Super(val a:Int, val b:Int)
class Child1(a2:Int, b2:Int): Super(a2,b2)
class Child2: Super {
    constructor():super(1,2)
}
  • オーバーライドできる要素にはopenを明示する必要がある
  • overrideしたメソッドを、さらに継承したクラスでoverrideするのを防ぐ場合はfinal
open class Super {
    open fun method() {
        println("parent")
    }
}

open class Child1 :Super(){
    override fun method() {
        super.method()
        println("child1")
    }
}

class Child2 :Child1(){
    override fun method() {
        super.method()
        println("child2")
    }
}

fun main(args: Array<String>) {
    Child2().method()
}
  • プロパティもオーバーライドできる
    • あんまり用途がわかってない
    • カスタムアクセサの拡張とかだろうか🍙
  • 派生クラスの初期化よりもベースクラスの初期化のが先に走る
  • ベースクラスのinitializerでopenなメンバを使わない
    • 派生クラスでoverrideしたメンバが初期化されてないのにinitializerで呼ばれる形になるので、予期しない動きをする可能性がある
  • ベースクラスが複数あって同じメンバが存在したらオーバーライド必須
  • クラスはstaticなメソッドを持てない
    • トップレベル関数を定義しよう
    • クラス経由で関数を呼びたいが、初期化はしない場合はオブジェクト宣言orコンパニオンオブジェクト

Properties and Fields

  • backing fieldの参照はカスタムアクセサを介さない
  • カスタムアクセサの中でフィールドを参照すると再帰になって死ぬ
  • backing propertiesの用途がよくわからない
  • lateinitをつけた変数はインスタンス生成時に初期化しなくてもコンパイルエラーにならない
    • ただし、初期化せずにコールすると例外
    • DIとかの文脈で使うらしい
      • Setterインジェクションとか?
      • Nullableでnullで初期化するより取り回しいいのかな?

interfaces

  • インターフェースはプロパティをもてる
    • が、abstructかカスタムアクセサの実装のみ
    • backing fieldはもてないし、カスタムアクセサから触れない
  • 複数のインターフェースを実装した時にシグネチャが被るメンバがあったらそいつはオーバーライドしないといけない

Visibility Modifiers

  • トップレベルに関数を定義できる
  • トップレベルの要素に対するVisibility Modifiers
    • privateはfile内から参照、internalはモジュール内から参照できる。protectedはつけられない
  • クラスのメンバに対するVisibility Modifiers
    • privateはクラス内、protectedはそのクラスとサブクラスから、internalはモジュール内から参照
  • モジュールはまとめてコンパイルした組み合わせのこと?🍙

Extensions

  • こんな感じですでにあるクラスを拡張できる
fun String.yeah(){
    println(this)
    println("yeah")
}

fun main(args: Array<String>) {
    "oh".yeah()
}
  • メンバと拡張関数のシグネチャが同じだとメンバが優先される
    • ハマりそう
  • Nullable型を拡張するとレシーバがNullableになる
    • レシーバがnullでも呼べる
  • 拡張プロパティ
    • カスタムアクセサだけ
    • プロパティとかフィールドとかの言葉の定義を一回整理したい🍙
  • クラスのなかで他のクラスを拡張できる
    • 定義したクラスの中でだけ有効っぽい
class C (val value:Int)

class D {
    fun C.a(){
        println(this.value)
    }

    fun b(c:C){
        c.a()
    }
}

fun main(args: Array<String>) {
    D().b(C(1))
}

Data Classes

  • Lombokの@Dataみたいな
    • 生成されたメソッドはprimary constructorで定義したメンバしか使わない

Generics

  • 型パラメータが推論できる場合は、コンストラクタ呼び出し時に省略できる

class A(val value:T) class B()

fun main(args: Array) { var a = A(1) var b = B() // コンパイルエラー }

  • in/outはこの記事がわかりやすかった
  • inは型パラメータが引数の型にだけ使われるマーク
    • だったら、Tが引数の型のメソッドがある
    • その型パラメータが設定されたクラスのメソッドは、Tの継承クラスを渡せるはず
  • outは型パラメータが戻り値の型にだけ使われるマーク
    • 戻り値を、そのクラスの親としてそのまま格納できる
  • ちょっとなんか怪しいのであとでもう一度🍙

Nested and Inner Classes

  • ネストされたクラスにinnerがついてるとouterを参照できる
class A (val value:Int){
    inner class B {
        fun print() {
            print(value)
        }
    }
}
  • 匿名クラスはobjectつける
interface A {
    fun print()
}

abstract class B {
    abstract fun print()
}

fun main(args: Array<String>) {
    val a = object : A {
        override fun print() {
            print("test")
        }
    }

    a.print()

    val b = object : B() {
        override fun print() {
            print("test")
        }
    }

    b.print()
}
  • Sam変換微妙に理解できてない🍙
  • Javaの関数型インターフェースにのみ使えるっぽい
fun test(s:Comparator<Int>) {
    s.compare(1,2)
}

fun main(args: Array<String>) {

    test(Comparator { o1, o2 -> o2 - o1 })
    test({ o1, o2 -> o2 - o1 }) // これなんでだめ?

}

Enum Classes

  • こんなんできる
enum class Test {
    A {
        override fun print() {
            println("AAAA")
        }
    },
    B {
        override fun print() {
            println("BBBB")
        }
    };

    abstract fun print()
}

fun main(args: Array<String>) {
    Test.A.print()
    Test.B.print()
}
  • interfaceを実装できる
    • メンバはclassに定義してもいいし、enum値に定義してもいい
interface A {
    fun A()
}

interface B {
    fun B()
}

enum class E:A,B {
    ENUM{
        override fun B() {
            println("BBBB")
        }
    };

    override fun A() {
        println("AAAA")
    }
}

fun main(args: Array<String>) {
    E.ENUM.A()
    E.ENUM.B()
}

Object Expressions and Declarations

  • なんかの方を継承したanonymous classのインスタンス生成には、object式を使う
  • object式に複数の型を渡す奴が何なのかよくわからん🍙
  • 匿名オブジェクトをpublicな関数で返すと、そのオブジェクトのメンバにはアクセスできない
  • クラスっぽい感じでobjectを宣言するとシングルトンになる
    • スレッドセーフ
    • 初期化はスレッドセーフ
    • 何かのクラスを継承できる
  • クラス内のオブジェクトはcompanionで宣言できる
  • コンパニオンオブジェクトがあんまり理解できてない?🍙

Type aliases

typealias Maaaap = Map<String, Map<String, String>>

fun main(args: Array<String>) {
    val map : Maaaap = mapOf("p" to mapOf("c" to "v"))
}
typealias F = (Int) -> Int

fun main(args: Array<String>) {
    var a:F = {a:Int -> a}
}
  • ネストされたクラスにも行ける
    • インナークラスとネストされたクラスの違いが理解できてない🍙
  • あくまでエイリアスで同様の型として扱われる
typealias Integer = String

fun method(value:String) {
    print(value)
}

fun main(args: Array<String>) {
    val ok:Integer = "YEAH"
    method(ok)
}

Inline classes

  • こういう使い方であってるんだろうか
class Yes {
    fun yes(){
        println("yes")
    }

}

inline class LoggingYes(val value: Yes) {
    fun yes(){
        log.info("--- yes start ---")
        value.yes()
        log.info("--- yes end ---")
    }
}
  • 普通のクラスとの違いがよくわからない🍙
    • これはパフォーマンスの話だけ?

Delegation

  • byに指定したプロパティの引数をオブジェクトでインターナルに保存し、そのクラスが持っている全てのメンバをbyが指定されたクラスのメンバとして扱える

Delegated Properties

  • カスタムアクセサの共通化のためにgetterとsetterを定義したクラスを作ってbyで委譲できる
  • lazyにLambdaを渡すと遅延評価できる
import kotlin.reflect.KProperty

class Data {

    var count:Int = 0
    val a:String by lazy {
        println("compute")
        count++
        "ohhhhhhhhhhhhhhhhhhhh"

    }
}

fun main(args: Array<String>) {
    val e = Data()
    println(e.count) // 0
    println(e.a) // ここでlazyに定義したLambdaが計算される
    println(e.count) // 1
    println(e.a) // 2回目はそのまま返す
    println(e.count) // 1
}
  • Delegates.observableはsetterの処理を委譲
    • 型と変更前、変更後の値が参照可能
import kotlin.properties.Delegates

class Data {
    var a:String by Delegates.observable("initial"){
        property, oldValue, newValue ->
        println("$property from $oldValue to $newValue")
    }
}

fun main(args: Array<String>) {
    val e = Data()
    e.a = "a" // var Data.a: kotlin.String from initial to a
}
  • vetoableはbooleanを返すラムダを定義してfalseを返すと値を更新しない
import kotlin.properties.Delegates

class Data {
    var a:String by Delegates.vetoable("initial"){
        property, oldValue, newValue ->
        println("$property from $oldValue to $newValue")

        if (newValue == "fuck") {
            false
        } else {
            true
        }
    }
}

fun main(args: Array<String>) {
    val e = Data()
    e.a = "a"
    println(e.a)
    e.a = "fuck" // この代入は無視される
    println(e.a) // a
}
  • なぜmapに委譲できるのかよくわからない 🍙
    • 委譲プロパティの要件を満たしてないように見えてる
  • local変数も委譲プロパティ使える
    • 使い所難しい気もする
  • provideDelegate理解できてない 🍙

Functions

  • デフォルトの引数は継承しても引き継ぐ
open class Yes {
    open fun hello(value:String = "hello") {
        println(value)
    }
}

class Yes2: Yes() {
    override fun hello(value: String) {
        super.hello(value)
        println("hello2")
    }
}

fun main(args: Array<String>) {
    Yes2().hello();
}
  • 戻り値が不要な場合、戻り値はUnitとなる
    • この時の型の指定はOptional
  • 1つの式だけの関数は中括弧を省略できる
fun a(a:Int, b:Int) = a * b

fun main(args: Array<String>) {
    println(a(2, 3)) // 6
}
  • 戻り値の型は推論されない
  • 可変長引数はvararg
  • infix function
infix fun String.join(value:String) = this + value

fun main(args: Array<String>) {
    println("YEAH" join "OHHHHHHHHHH")
}
  • ローカルな関数定義ができる
    • あんまり用途わかってない
fun main(args: Array<String>) {
    fun yes() {
        println("yes")
    }

    yes()
}

Higher-Order Functions and Lambdas

  • 関数型は関数型インターフェースじゃなくてこんな感じ
val sum1 = { x: Int, y: Int -> x + y }
val sum2:(Int, Int) -> Int = { x,y -> x + y }

fun main(args: Array<String>) {
    println(sum1.invoke(1, 2))
    println(sum2.invoke(1, 2))
}
fun test(text:String, func: (String) -> String){
    println(text)
    println(func(text))
}

fun main(args: Array<String>) {
    test("yes", {it + "func"}) // 引数が一つならitで参照できる
    test("yes"){it + "func"} // 関数型の引数が最後なら外に出せる
}
  • 無名関数だとこうなる
fun test(text:String, func: (String) -> String){
    println(text)
    println(func(text))
}

fun main(args: Array<String>) {

    var a = fun(a:String): String {
        return a + "func";
    }

    test("yes", a)
}

* 外側のスコープの変数にアクセスできるし、変更もできる

fun main(args: Array<String>) {
    var a = 1
    var b = {println("b");a = 100}
    println(a) // 1
    b() // bの関数をコール
    println(a) // 100
}
fun main(args: Array<String>) {
    val join = fun String.(arg:String): String = this + arg // レシーバ付き関数は
    println("yes".join(" no")) // yes no // このノリで使える
}