2016/12/25の30分 Kotlinメモ🍰
2016/12/25の30分 Kotlinメモ🍰
書いてるコードは雑にここにあります。
Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。
Kotlinスタートブック -新しいAndroidプログラミング
- 作者: 長澤太郎
- 出版社/メーカー: リックテレコム
- 発売日: 2016/07/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Class Delegation
前も書いたけど、これはよい。
そしてinterfaceのメソッドの引数にもデフォルト引数使えるんだーという発見。
interface GreeterKai { // sayHello()で呼び出すとデフォルト引数の方じゃなくて、引数なしで定義したメソッドが呼ばれるF fun sayHello() // デフォルト引数は指定できるのね fun sayHello(target: String = "匿名") } class JapaneseGreeterKai : GreeterKai { override fun sayHello() { sayHello("匿名") } override fun sayHello(target: String) { println("こんにちは、$target!") } } class GreeterWithRecording(private val greeterKai: GreeterKai) : GreeterKai by greeterKai { private val _target: MutableSet<String> = mutableSetOf() val targets: Set<String> get() = _target override fun sayHello(target: String) { _target += target greeterKai.sayHello(target) } } val gr = GreeterWithRecording(JapaneseGreeterKai()) gr.sayHello("test") // こんにちは、test! gr.sayHello() // こんにちは、匿名! gr.sayHello("kotlin") // こんにちは、kotlin! println(gr.targets) // [test, kotlin]
Generics
今のところ出てきたものはJavaとそこまで変わらず。
where
がちょっと変わってるかなー?みたいなところかねー
class Container<T>(val value: T) { } // Javaで書く T extends Collection<String> class Container2<T : Collection<String>>(val value: T) { } class Container3<T>(val value: T) where T : Collection<String>, T : List<String> { } interface A { } interface B { } class Container4<T>(val value: T) where T : A, T : B { }
まとめ
メリークリスマス🍰
2016/12/24の30分 Kotlinメモ⚡
2016/12/24の30分 Kotlinメモ⚡
書いてるコードは雑にここにあります。
Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。
Kotlinスタートブック -新しいAndroidプログラミング
- 作者: 長澤太郎
- 出版社/メーカー: リックテレコム
- 発売日: 2016/07/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Interfaces
デフォルト実装が持てるのと、プロパティ(も持てるのが興味深い。
プロパティもabstractなものと、デフォルトなものが持てると。
interface GreeterKai { // プロパティも持てる(プロパティ自体が値を持つものは宣言できない = varは無理.val) // 固定値 or 他のプロパティなら返せる val hum: String get() = "hum" // デフォルト実装を持てる fun hum() { println(language) } val language: String fun sayHello(target: String) }
実装するとこんな感じ。
class EnglishGreeterKai : GreeterKai { override val language = "English" override fun sayHello(target: String) { println("Hello $target!") } }
interfaceの継承
interfaceは別のinterfaceを継承することができると。
ここでもプロパティの扱いがどうなるか見てみた。
interface内ではやっぱりプロパティは値を持てないのね。
interface Homu { val homu1: Int var homu: Int fun homu() } interface Humu : Homu { // interface内のプロパティは値を持てない(バッキングフィールドを持てない) // 他のinterfaceが持つプロパティをoverrideしても、返せるのは固定値 or 他のプロパティ override val homu1: Int get() = 0 fun humu() }
ちなみにResolving overriding conflictsについて書いてあるけど、実際にそういうケースに出くわしたことがない気がするので割愛。
出くわした場合でもそんな難しいことではないしねー。
まとめ
いかんせんプロパティの扱いになれないですなー...⚡
2016/12/23の30分 Kotlinメモ😏
2016/12/23の30分 Kotlinメモ
書いてるコードは雑にここにあります。
Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。
Kotlinスタートブック -新しいAndroidプログラミング
- 作者: 長澤太郎
- 出版社/メーカー: リックテレコム
- 発売日: 2016/07/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Extension Properties
プロパティも拡張できるのか。便利だなーまったく!!
// 拡張プロパティ // バッキングフィールドは持てない val String.countWords: Int get() = split("""\s+""".toRegex()).size println("Kotlin Kotlin Kotlin!!".countWords) // 3
継承
継承していいものにopen
つけろよ!ってところ以外はだいたいJavaと同じかなー。
プロパティもoverrideできるのか!?ってことには驚いた!できるのか、そうか。
open class Person(val name: String) { open var age: Int = 0 open fun introduce() { println("I am $name2.") } } class Student(name: String, val id: Long) : Person(name) { override var age: Int = 0 get() = field set(value) { field = value * 2 } override fun introduce() { println("I am $name(id=$id).") } } // super classの型にsub classの型は入る val p2: Person = Student("kotlin", 1L) p2.introduce()
Abstract Classes
これはほぼJavaと同じかなー
そしてプロパティをabstractにできるのか!?できるのか、そうか。
abstract class Greeter(val target: String) { abstract var code: String abstract val age: Int abstract fun sayHello() } class EnglishGreeter(target: String, override val age: Int) : Greeter(target) { override var code: String = "" get() = "en" set(value) { field = value } override fun sayHello() { println("Hello $target!") } } class JapaneseGreeter(target: String, override val age: Int) : Greeter(target) { override var code: String = "" get() = "ja" set(value) { field = value } override fun sayHello() { println("こんにちは、$target!") } }
まとめ
冬休みもKotlinガンバルぞい!
2016/12/22の30分 Kotlinメモ🎲
2016/12/22の30分 Kotlinメモ🎲
書いてるコードは雑にここにあります。
Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。
Kotlinスタートブック -新しいAndroidプログラミング
- 作者: 長澤太郎
- 出版社/メーカー: リックテレコム
- 発売日: 2016/07/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Properties and Fields
プロパティはあくまで窓口であり、実際に値を保持するBacking Fieldにはプロパティ内部でしかアクセスできないと。
Backing Field = 実際の値の参照を保持するもの?みたいな?
class Person { var name: String = "" set(value) { println("set $value") // field = バッキングフィールドを表す暗黙の変数 field = value } var age: Int = 0 }
以下のnameLength
プロパティはBacking Fieldは生成されない。
class Person { var name: String = "" set(value) { println("set $value") // field = バッキングフィールドを表す暗黙の変数 field = value } var age: Int = 0 val nameLength: Int get() = name.length }
Javaをやってて、プロパティ謎いぞ!フィールドと何が違うの!ってなったけど、@sys1yagiさんが書いてる以下を読んだら納得できた。
バッキングフィールド?なんだそれ?となったら、読んでみるとよい。
Late-Initialized Properties
Backing Fieldを持つプロパティは必ず初期化する必要があるけど、lateinit
をつければ初期化タイミングを遅らせることができるよ!ってことらしい。
使用できるプロパティに色々制限はあるので、用途は限られそう。
class Person { // 初期化のタイミングを遅らせる // varでしか使えない + non nullでしか使えない + primitiveには使えない + custom getter/setterは持てない // https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties // DIとかに使える // 初期化する前にアクセスするとUninitializedPropertyAccessExceptionが起きる lateinit var humuhumu: String } val p = Person() // println(p.humuhumu) // kotlin.UninitializedPropertyAccessException: lateinit property humuhumu has not been initialized p.humuhumu = "humuhumu" println(p.humuhumu) // humuhumu
まとめ
プロパティの謎が少しずつわかってきたのでたのしいたのしい🎲
2016/12/21の30分 Kotlinメモ🍥
2016/12/21の30分 Kotlinメモ🍥
書いてるコードは雑にここにあります。
Kotlinスタートブック -新しいAndroidプログラミング を引き続き読んでる。
Kotlinスタートブック -新しいAndroidプログラミング
- 作者: 長澤太郎
- 出版社/メーカー: リックテレコム
- 発売日: 2016/07/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
Object Expressions
object
ね!
なんか色々できるので、どんな用途で使うのがいいんだろーと悩む🤔
きっといつか答えが出るだろう...!
Interface
Javaと基本同じだけど、プロパティを持てることに驚いたぞ!!
interface BucketKai { fun fill() fun drainAway() fun pourTo(that: BucketKai) // interfaceはプロパティを持てる // プロパティはオブジェクトの内部にあるものではなく、境界にあるもの // 変数のように見えるが、実際のデータの持ち方は規定しない // 実装するオブジェクトの実装次第になる val capacity: Int var quantity: Int }
オブジェクト式で生成するとこんな感じで実装して使える。
fun createBucketKai(_capacity: Int): BucketKai = object : BucketKai { // プロパティにもoverrideがつく override val capacity = _capacity // プロパティは必ず初期化しないといけない override var quantity = 0 override fun fill() { quantity = capacity } override fun drainAway() { quantity = 0 } override fun pourTo(that: BucketKai) { val thatVacuity = that.capacity - that.quantity if (quantity <= thatVacuity) { that.quantity = quantity drainAway() } else { that.fill() quantity -= thatVacuity } } } val bucketKai1 = createBucketKai(7) val bucketKai2 = createBucketKai(4) bucketKai1.fill() bucketKai1.pourTo(bucketKai2) println(bucketKai1.quantity) // 3 println(bucketKai2.quantity) // 4
Class
上で使ったInterface BucketKai
をクラスで実装するとこんな感じ。
class BucketImpl(override val capacity: Int) : BucketKai { override var quantity = 0 override fun fill() { quantity = capacity } override fun drainAway() { quantity = 0 } override fun pourTo(that: BucketKai) { val thatVacuity = that.capacity - that.quantity if (quantity <= thatVacuity) { that.quantity = quantity drainAway() } else { that.fill() quantity -= thatVacuity } } }
まとめ
どの絵文字使ってないか忘れてきたぞい...🍥