https://my.oschina.net/u/3847608/blog/1837610
今回はKotlinの変数と定数について説明しましたが、主に以下を紹介します。
- 1.変数の基本的な定義
- 2.varとvalの違い
- 3.インテリジェント型推論
- 4.カスタム属性アクセサー
- 5. varは可変であり、valは不変でなければなりませんか?
1.KotlinとJavaでの可変使用量と定数使用量の比較
- 1.Javaで変数と定数を定義します
public String name = "Mikyou";//定义变量
public final int age = 18;//final定义常量
- 2.Kotlinで変数と定数を定義します
var name: String = "Mikyou"
val age: Int = 18
または
var name = "Mikyou"
val age = 18
要約:上記の比較から、次のことがわかります。
- 1. Kotlinは、Javaよりも簡潔で柔軟な変数と定数を定義しています
- 2. Kotlinには型推論メカニズムがあります。変数または定数を初期化する場合、型宣言を省略でき、初期化された値の型に応じて変数の型として使用されます。
- 3. Kotlinは、変数と定数はvar(変数)、val(定数)キーワードを使用し、次に名前、最後にタイプを使用する必要があることを宣言します(初期化された値タイプがある場合は、直接省略できます)
- 4. Javaと比較して、Kotlinのデフォルトのアクセス修飾子はパブリックであり、Javaがデフォルトです
- 5. Javaは通常、型から始まり、次に名前で始まり、型を省略することはできません。この種の操作はKotlinでは不可能です。Kotlinでは型を省略できるため、つまり型は比較的弱いため、Kotlinは型を最後に配置します。通常、初期化値を含めると、後続の型宣言が省略されます。
2つ目は、Kotlinの可変で一定の使用法です。
var name: String = "Mikyou"
var address: String?//如果这个变量没有初始化,那么需要显示声明类型并且指明类型是否可null
address = "NanJing"
val age: Int = 18
または
var name = "Mikyou"
val age = 18
- 1.変数と定数宣言は、キーワード「var」と「val」で始まる必要があります。
- 2.変数と定数の構造:(変数またはval)名前:(コンマの分割)変数タイプ=初期化値。
- 3.インテリジェントな型変換(コンパイラはスマートキャストとしてプロンプトを表示します)。変数または定数に初期値が含まれている場合、型は省略できます。コンパイラは、初期化された値の型をデフォルトで変数および定数型として分析します。
- 4.変数が初期化されていない場合は、宣言された型を表示し、型がNULL可能かどうかを指定する必要があります。
3つ目は、Kotlinのカスタム属性アクセサーです。
属性はKotlinのファーストクラスの機能であり、Javaのフィールドとsetterおよびgetterメソッドを属性に置き換えるために使用されます。Kotlinのsetおよびgetアクセサーは、Javaのsetterおよびgetterメソッドと同等です。Kotlinの新機能は、setterおよびgetterアクセサーを含む、クラス内のプロパティのアクセサーを定義できることです。この機能は、複数の属性ロジックを介して計算する必要がある新しい属性に非常に適しています。その場合、論理計算のプロセス操作は、Javaのようなメソッドを開いて実行する必要はありません。属性アクセサで直接論理演算を実行できます。
- 1.カスタムget属性アクセサー
Javaで実装:
public class Rectangle {
private float width;
private float height;
public Rectangle(float width, float height) {
this.width = width;
this.height = height;
}
public boolean isSquare() {//在java中实现一个方法进行相关的逻辑计算
return width == height;
}
}
Kotlinで実装:
class Rectangle(width: Float, height: Float) {
val isSquare: Boolean//在Kotlin中只需要一个属性就能解决,重新定义了isSquare的getter属性访问器,访问器中可以写入具体逻辑代码。
get() {
return width == height
}
}
- 2.カスタムセット属性アクセサー
JavaのAndroidのカスタムビューにsetterメソッドを実装します。
public class RoundImageView extends ImageView {
...
public void setBorderColor(int color) {
mColor = color;
invalidate();
}
...
}
KotlinのAndroidのカスタムビューにsetattributeアクセサーを実装します。
class RoundImageView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defAttrStyle: Int = 0)
: ImageView(context, attributeSet, defAttrStyle) {
var mBorderColor: Int
set(value) {//自定义set属性访问器
field = value
invalidate()
}
}
第4に、Kotlinのvarとvalの違い
- 1、var(変数から)変数参照。また、それによって変更された変数の値は、読み取りおよび書き込み権限で変更できます。これは、Javaの非最終変数と同等です。
- 2. Val(値から)は不変の参照です。また、それによって変更された変数の値は通常初期化され、後の段階で再スローすることはできません。そうしないと、コンパイル例外がスローされます(この文については、Kotlinの不変で読み取り可能なvalの説明を参照してください)。 、これはJavaの最終修正定数と同等です。
- 3. Kotlin開発プロセスでは、valキーワードを使用して、すべてのKotlin変数を可能な限り宣言します。varを使用するのは特別な場合のみです。Kotlinの関数は第一級市民であり、関数型プログラミングコンテンツがたくさんあることは誰もが知っています。不変の参照変数を使用すると、関数型プログラミングのスタイルに近づきます。
- 4. val参照自体は不変ですが、それが指すオブジェクトは変更可能である可能性があることに注意してください(この問題の説明と検証については、Kotlinの不変で読み取り可能なvalの説明を参照してください)。
- 5. varキーワードでは値を変更できますが、タイプは変更できません。
5.Kotlinでのvalの不変性と可読性に関する議論
Kotlinは新しい言語であるため、学習の過程でいくつかのいわゆる定理を習慣的に覚えており、なぜそうなるのかについてはあまり深く理解していませんでした。たとえば、今日のトピックを取り上げると、多くの人が(最初の私を含めて)var変更変数は変更可能であるのに対し、val変更変数は不変であると考えていると思います。次に、Kotlinのカスタム属性アクセサーを学習した後、問題があると感じます。それから外国のブログを見に行きました。説明はありますが、読んだ後、valで変更した変数の値を変更して読み取ることができ、基になる参照も変更されるので、さらに混乱します。最初の文は確かに理解できますが、後者の文はまだ予約されています。そこで、デモ認証を書き始めました。外国のブログの元の文を引用する「しかし、valは、オブジェクトへの基になる参照が不変であることを保証すると言えますか?いいえ...」外国のブログのソースアドレス
- 1.valが不変で読み取り可能であるという仮定
仮説1:Kotlinでvalによって変更された変数は不変であるとは言えず、valによって変更された変数の許可は読み取り可能であるとしか言えません。
仮説2:Koltinでvalによって変更された変数への参照は不変ですが、ポイントされたオブジェクトは変数です。
- 2.valは不変で読み取り可能であるという議論
引数仮説1:Kotlinでの開発中、valで変更された変数を再度割り当てることはできません。そうしないと、コンパイル時の例外がスローされます。ただし、再度割り当てることができないという事実は、不変であることを意味するものではありません。Kotlinはカスタム属性アクセサーの機能がJavaとは異なるためです。この機能は、valによって変更された変数の不変性と矛盾しているようです。この問題はJavaには存在しません。最終的に変更された変数が使用される場合、いわゆるカスタムアクセサーの概念はありません。
fun main(args: Array<String>) {
val name = "Hello Kotlin"
name = "Hello Java"
}
印刷エラー:
Error:(8, 5) Kotlin: Val cannot be reassigned
get属性アクセサーの例を定義する
class RandomNum {
val num: Int
get() = Random().nextInt()
}
fun main(args: Array<String>) {
println("the num is ${RandomNum().num}")
}
印刷結果:
the num is -1411951962
the num is -1719429461
概要:上記の例は、仮説1が真であることを示しています。Kotlinでvalによって変更された変数は、不変であるとは言えず、読み取り可能な権限しかありません。
引数仮説2:引数1から、Kotlinのvalによって変更された変数は可変であることがわかっているので、その基になる参照は可変ですか?外国のブログによると、引用はさまざまですが、本当ですか?説明する例を通して。
ユーザークラス:
package com.mikyou.kotlin.valtest
open class User() {
var name: String? = "test"
var age: Int = 18
var career: String? = "Student"
}
学生クラス:
class Student() : User()
教師のカテゴリ:
class Teacher() : User()
顧客インターフェース:
interface Customer {
val user: User//注意: 这里是个val修饰的User实例引用
}
VipCustomer実装クラス:
class VipCustomer : Customer {
override val user: User
get() {
// return Student().apply {
// name = "mikyou"
// age = 18
// career = "HighStudent"
// }
return Teacher().apply {
//看到这里很多人肯定认为,底层引用也会发生改变,毕竟Student, Teacher是不同的对象了。但是事实是这样的吗?
name = "youkmi"
age = 28
career = "HighTeacher"
}
}
}
テスト:
fun main(args: Array<String>) = VipCustomer().user.run {
println("my name is $name, I'm $age years old, my career is $career, my unique hash code is ${hashCode()} ")
}
印刷結果:
my name is mikyou, I'm 18 years old, my career is HighStudent, my unique hash code is 666988784
//切换到Teacher
my name is youkmi, I'm 28 years old, my career is HighTeacher, my unique hash code is 666988784
要約:上記の例から、仮説2が真であることが示されます.2つの異なるオブジェクトhashCodesは、ユーザーの参照アドレスが変更されておらず、参照が指すオブジェクトを変更できることを示します。
これで、Kotlinエントリの基本的な文法は終わりです。次の記事では、Kotlin関連のコンテンツについて詳しく説明します。