Skip to content

Commit 90d08d8

Browse files
committed
update
1 parent 482d6ae commit 90d08d8

6 files changed

+71
-91
lines changed

KotlinCourse/1.Kotlin_简介&变量&类&接口.md

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
and first-class delegation`等实现
3232
- `Kotlin`可与`Java`语言无缝通信。这意味着我们可以在`Kotlin`代码中使用任何已有的`Java`库;同样的`Kotlin`代码还可以为`Java`代码所用
3333
- `Kotlin`在代码中很少需要在代码中指定类型,因为编译器可以在绝大多数情况下推断出变量或是函数返回值的类型。这样就能获得两个好处:简洁与安全
34-
- Kotlin 是一种静态类型的语言。这意味着,类型将在编译时解析且从不改变
34+
- `Kotlin`是一种静态类型的语言。这意味着,类型将在编译时解析且从不改变
3535

3636

3737
## `Kotlin`优势
@@ -195,13 +195,13 @@ var weight = 70.5 // double
195195
val bitwiseAnd = FLAG1 and FLAG2
196196
```
197197

198-
- 一个`String`可以像数组那样访问,并且被迭代:
198+
- 一个`String`可以像数组那样访问,并且也可以被迭代:
199199
```kotlin
200200
var s = "charon"
201201
var c = s[2]
202202

203203
for (a in s) {
204-
Log.e("@@@", a +"");
204+
Log.e("@@@", a + "");
205205
}
206206
```
207207

@@ -263,11 +263,11 @@ class MainActivity : AppCompatActivity() {
263263
}
264264
```
265265

266-
## 后端变量`Backing Fields`.
266+
## 后端变量`Backing Fields`
267267

268268
`Kotlin`会默认创建`set get`方法,我们也可以自定义`get set`方法:
269269

270-
`kotlin``getter``setter`是不允许本身的局部变量的,因为属性的调用也是对`get`的调用,因此会产生递归,造成内存溢出。
270+
`kotlin``getter``setter`是不允许调用本身的局部变量的,因为属性的调用也是对`get`的调用,因此会产生递归,造成内存溢出。
271271

272272
例如:
273273

@@ -319,7 +319,7 @@ var myProperty: String
319319
## 延迟初始化
320320

321321
我们说过,在类内声明的属性必须初始化,如果设置非`null`的属性,应该将此属性在构造器内进行初始化。
322-
假如想在类内声明一个`null`属性,在需要时再进行初始化(最典型的就是懒汉式单例模式),`Kotlin`的规则是相背的,此时我们可以声明一个属性并延迟其初始化,此属性用`lateinit`修饰符修饰。
322+
假如想在类内声明一个`null`属性,在需要时再进行初始化(最典型的就是懒汉式单例模式),这就与`Kotlin`的规则是相背的,此时我们可以声明一个属性并延迟其初始化,此属性用`lateinit`修饰符修饰。
323323

324324
```kotlin
325325
class MainActivity : AppCompatActivity() {
@@ -400,7 +400,7 @@ val sex: String by lazy(LazyThreadSafetyMode.NONE) {
400400

401401
## 类的定义:使用`class`关键字
402402

403-
当你在定义类的时候,你需要想想该类所创建的对象需要什么。你需要考虑
403+
当你在定义类的时候,需要想想该类所创建的对象需要什么
404404

405405
- 每个对象自身的特点
406406

@@ -456,7 +456,7 @@ val myDog = Dog("Fido", 70, "Mixed" )
456456

457457
![Image](https://raw.githubusercontent.com/CharonChui/Pictures/master/kotlin_class_dog.jpg?raw=true)
458458

459-
类中所定义的函数又称为成员函数有时也被称为方法。
459+
类中所定义的函数又称为成员函数有时也被称为方法。
460460

461461
#### 创建对象的执行过程
462462

@@ -587,7 +587,7 @@ class Bird (weight: Double = 0.00, age: Int = 0, color: String = "blue"){
587587
Kotlin引入了一种叫作init语句块的语法,它属于上述构造方法的一部分,两者在表现形式上却是分离的。Bird类的构造方法在类的外部,它只能对参数进行赋值。如果我们需要在初始化时进行其他的额外操作,那么我们就可以使用init语句块来执行。比如:
588588

589589
```kotlin
590-
class Bird(weight: Double, aget: Int, color: String) {
590+
class Bird(weight: Double, age: Int, color: String) {
591591
init {
592592
println("the weight is ${weight}")
593593
}
@@ -611,16 +611,14 @@ class Bird(weight: Double, aget: Int, color: String) {
611611
val weight: Double
612612
val age: Int
613613
val color: String
614+
init {
615+
this.weight = weight
616+
this.age = age
617+
}
618+
init {
619+
this.color = color
620+
}
614621
}
615-
616-
init {
617-
this.weight = weight
618-
this.age = age
619-
}
620-
init {
621-
this.color = color
622-
}
623-
624622
```
625623

626624
可以发现,多个init语句块有利于进一步对初始化的操作进行职能分离,这在复杂的业务开发中显得特别有用。
@@ -768,31 +766,7 @@ class Person // 从 Any 隐式继承
768766
```
769767

770768
`Any`不是`java.lang.Object`。它除了`equals()``hashCode()``toString()`外没有任何成员。
771-
`Kotlin`中所有的类默认都是不可继承的(`final`),为什么要这样设计呢?引用`Effective Java`书中的第17条:要么为继承而设计,并提供文档说明,
772-
要么就禁止继承。所以我们只能继承那些明确声明`open`或者`abstract`的类:要声明一个显式的超类型,我们把类型放到类头的冒号之后:
773-
774-
```kotlin
775-
open class Person(num: Int)
776-
// 继承
777-
class SuperPerson(num: Int) : Person(num)
778-
```
779-
780-
冒号后面的Person(num)会调用Person类的构造函数,以确保所有的初始化代码(例如给属性赋值)能够被执行。调用父类构造函数是强制性的:如果父类有主构造函数,你必须在子类头中调用它,否则代码将无法通过编译。请记住,即使你没有在父类中显式地添加构造函数,编译器也会在编译代码的时候自动创建一个空构造函数。假如我们不想为Person类添加构造函数,因此编译器在编译代码的时候创建了一个空构造函数。该构造函数通过使用Person()被调用。
781-
782-
783-
784-
如果该类有一个主构造函数,其基类必须用基类型的主构造函数参数就地初始化。
785-
如果类没有主构造函数,那么每个次构造函数必须使用`super`关键字初始化其基类型,或委托给另一个构造函数做到这一点。
786-
注意,在这种情况下,不同的次构造函数可以调用基类型的不同的构造函数:
787-
788-
```kotlin
789-
class MyView : View {
790-
constructor(ctx: Context) : super(ctx)
791-
constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
792-
}
793-
```
794-
795-
在Java中,类默认是可以被继承的,除非你主动加final修饰符。而在Kotlin中恰好相反,默认是不可被继承的,除非你主动加可以继承的修饰符,那便是open,如果不加open,那它在转化为Java代码时就是final的:
769+
`在Java中,类默认是可以被继承的,除非你主动加final修饰符。而在Kotlin中恰好相反,默认是不可被继承的,除非你主动加可以继承的修饰符,那便是open,如果不加open,那它在转化为Java代码时就是final的:
796770

797771
```kotlin
798772
class Bird {
@@ -825,6 +799,27 @@ public final class Bird {
825799
}
826800
```
827801

802+
所以Kotlin`中所有的类默认都是不可继承的(`final`),为什么要这样设计呢?引用`Effective Java`书中的第17条:要么为继承而设计,并提供文档说明,
803+
要么就禁止继承。所以我们只能继承那些明确声明`open`或者`abstract`的类:要声明一个显式的超类型,我们把类型放到类头的冒号之后:
804+
805+
```kotlin
806+
open class Person(num: Int)
807+
// 继承
808+
class SuperPerson(num: Int) : Person(num)
809+
```
810+
811+
冒号后面的Person(num)会调用Person类的构造函数,以确保所有的初始化代码(例如给属性赋值)能够被执行。调用父类构造函数是强制性的:如果父类有主构造函数,你必须在子类头中调用它,否则代码将无法通过编译。请记住,即使你没有在父类中显式地添加构造函数,编译器也会在编译代码的时候自动创建一个空构造函数。假如我们不想为Person类添加构造函数,因此编译器在编译代码的时候创建了一个空构造函数。该构造函数通过使用Person()被调用。
812+
813+
如果该类有一个主构造函数,其基类必须用基类型的主构造函数参数就地初始化。
814+
如果类没有主构造函数,那么每个次构造函数必须使用`super`关键字初始化其基类型,或委托给另一个构造函数做到这一点。
815+
注意,在这种情况下,不同的次构造函数可以调用基类型的不同的构造函数:
816+
817+
```kotlin
818+
class MyView : View {
819+
constructor(ctx: Context) : super(ctx)
820+
constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
821+
}
822+
```
828823

829824

830825
### Any
@@ -1090,7 +1085,7 @@ fun main(args: Array<String>) {
10901085
}
10911086
```
10921087

1093-
从Kotlin1.3版本器,你可以忽略main函数的参数,写成如下形式:
1088+
从Kotlin1.3版本起,你可以忽略main函数的参数,写成如下形式:
10941089

10951090
```kotlin
10961091
fun main() {
@@ -1105,7 +1100,7 @@ fun main() {
11051100
### 可变长参数函数:使用`vararg`关键字
11061101

11071102
```kotlin
1108-
fun vars(vararg v:Int){
1103+
fun vars(vararg v: Int){
11091104
for(vt in v){
11101105
print(vt)
11111106
}

KotlinCourse/2.Kotlin_高阶函数&Lambda&内联函数.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class CountryTest {
154154
countryApp.filterContries(countries, countryTest::isBigEuropeanCountry)
155155
```
156156

157-
经过重构后的程序显然比之前要优雅许多,程序可以根据任意的筛选需求,调用同一个filterCountries方法来获取国家数据。
157+
经过重构后的程序显然比之前要优雅许多,程序可以根据任意的需求筛选,调用同一个filterCountries方法来获取国家数据。
158158

159159
#### 方法引用表达式更多使用场景
160160

@@ -187,10 +187,6 @@ fun main(args: Array<String>) {
187187
}
188188
```
189189

190-
191-
192-
193-
194190
## 匿名函数
195191

196192
再来思考下上面代码中的CountryTest类,这仍算不上是一种很好的方案。因为每增加一个需求,我们都需要在类中专门写一个新增的筛选方法。然而Shaw的需求很多都是临时性的,不需要被复用。Shaw觉得这样还是比较麻烦,他打算用匿名函数对程序进一步的优化。
@@ -250,7 +246,7 @@ val foo = { x: Int ->
250246

251247

252248
> “Lambda 表达式”(lambda expression)其实就是匿名函数,`Lambda`表达式基于数学中的`λ`演算得名,直接对应于其中的`lambda`抽象
253-
> `(lambda abstraction)`,是一个匿名函数,即没有函数名的函数。`Lambda`表达式可以表示闭包(注意和数学传统意义上的不同)
249+
> `(lambda abstraction)`,是一个匿名函数,即没有函数名的函数。`Lambda`表达式可以表示闭包。
254250
255251

256252

@@ -289,7 +285,7 @@ Runnable runnable2=()->{
289285
- 函数体(如果存在的话)在`->`后面。
290286

291287
`Lambda`表达式是定义匿名函数的简单方法。由于`Lambda`表达式避免在抽象类或接口中编写明确的函数声明,进而也避免了类的实现部分,
292-
所以它是非常有用的。`Kotlin`语言中,可以将一函数作为另一个函数的参数。
288+
所以它是非常有用的。
293289

294290
`Lambda`表达式由箭头左侧函数的参数(在圆括号里的内容)定义的,将值返回到箭头右侧。
295291
`view.setOnClickListener({ view -> toast("Click")})`
@@ -397,7 +393,7 @@ val addFive: (Int) -> Int = { x -> x + 5 }
397393
由于lambda具有单独的参数x,而且编译器能够推断出x为Int类型,因此我们可以省略该x参数,并在lambda的主体中使用it替换它:
398394

399395
```kotlin
400-
val addFive: (Int) - Int = { it + 5 }
396+
val addFive: (Int) -> Int = { it + 5 }
401397
```
402398

403399
在上述代码中,{it+5}等价于{x->x+5},但更加简洁。请注意,你只能在编译器能够推断该参数类型的情况下使用it语法。例如,以下代码将无法编译,因为编译器不知道it应该是什么类型:

KotlinCourse/3.Kotlin_数字&字符串&数组&集合.md

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
前面介绍了基本语法和编码规范后,接下来学习下基本类型。
55

66
`Kotlin`中,所有东西都是对象,在这个意义上讲我们可以在任何变量上调用成员函数和属性。 一些类型可以有特殊的内部表示——例如,
7-
数字、字符和布尔值可以在运行时表示为原生类型值,但是对于用户来说,它们看起来就像普通的类。 在本节中,我们会描述`Kotlin`中使用的基本类型:
8-
数字、字符、布尔值、数组与字符串。
7+
数字、字符和布尔值可以在运行时表示为原生类型值,但是对于用户来说,它们看起来就像普通的类。
98

109
### 数字
1110

@@ -197,7 +196,8 @@ val str = "$s.length is ${s.length}" // 求值结果为 "abc.length is 3"
197196
Kotlin中的判等性主要有两种类型:
198197

199198
- 结构相等。通过操作符==来判断两个对象的内容是否相等。
200-
- 引用相等。通过操作符===来判断两个对象的引用是否一样,与之相反的判断操作符是!==。如果比较的是运行时的原始类型,比如Int,那么===判断的效果也等价于==。
199+
- 引用相等。通
200+
引用相等由`===`以及其否定形式`!===`操作判断。`a === b`当且仅当`a``b`指向同一个对象时求值为`true`。如果比较的是运行时的原始类型,比如Int,那么===判断的效果也等价于==。
201201

202202
```kotlin
203203
var a = "Java"
@@ -214,13 +214,6 @@ c === f // false
214214
```
215215

216216

217-
218-
### 引用相等
219-
220-
引用相等由`===`以及其否定形式`!===`操作判断。`a === b`当且仅当`a``b`指向同一个对象时求值为`true`
221-
222-
### 结构相等
223-
224217
结构相等由`==`以及其否定形式`!==`操作判断。按照惯例,像`a == b`这样的表达式会翻译成
225218
`a?.equals(b) ?: (b === null)`
226219
也就是说如果`a`不是`null`则调用`equals(Any?)`函数,否则即`a``null`检查`b`是否与`null`引用相等。
@@ -254,14 +247,14 @@ print(boxedA == anotherBoxedA) // 输出“true”
254247
我们就不能在定义这个类之外的文件中使用它。
255248
另一方面,如果我们在一个类里面使用了private修饰符,那访问权限就被限制在这个类里面了。甚至是继承这个类的子类也不能使用它。
256249

257-
- `protected`.
250+
- `protected`
258251
在Java中是包、类及子类可访问,而在Kotlin中只允许类及子类。
259252

260253
- `internal`
261254
它与Java的default有点像但也有所区别。如果是一个定义为`internal`的包成员的话,对所在的整个`module`可见。如果它是一个其它领域的成员,它就需要依赖那个领域的可见性了。
262255
比如如果写了一个`private`类,那么它的`internal`修饰的函数的可见性就会限制与它所在的这个类的可见性。
263256

264-
- `public`.
257+
- `public`
265258
你应该可以才想到,这是最没有限制的修饰符。这是默认的修饰符,成员在任何地方被修饰为public,很明显它只限制于它的领域。
266259

267260
### 数组
@@ -525,14 +518,14 @@ str?.length
525518
这么写编译器是能通过的,那么`result`的类型是什么呢?在`Kotlin`中,编译器会自动根据结果判断变量的类型,翻译成普通代码如下:
526519

527520
```kotlin
528-
if(str == null)
529-
result = null; // 这里result为一个引用类型
530-
else
531-
result = str.length; // 这里result为Int
521+
if(str == null) {
522+
result = null // 这里result为一个引用类型
523+
} else {
524+
result = str.length // 这里result为Int
525+
}
532526
```
533527

534-
那么如果我们需要的就是一个`Int`的结果(事实上大部分情况都是如此),那又该怎么办呢?在`kotlin`中除了`?`表示可为空以外,还有一个新的符号`:`
535-
感叹号`!!`,表示一定不能为空。所以上面的例子,如果要对`result`进行操作,可以这么写:
528+
那么如果我们需要的就是一个`Int`的结果(事实上大部分情况都是如此),那又该怎么办呢?在`kotlin`中除了`?`表示可为空以外,还有一个新的符号:双感叹号`!!`,表示一定不能为空。所以上面的例子,如果要对`result`进行操作,可以这么写:
536529

537530
```kotlin
538531
var str : String? = null

KotlinCourse/4.Kotlin_表达式&关键字.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ for (i in 4 downTo 1 step 2) println(i)
172172
```kotlin
173173
var nums = 1 until 100
174174
for(num in nums) {
175-
println(num)
176-
// 这样打印出来是1 2 3 .....99
175+
println(num)
176+
// 这样打印出来是1 2 3 .....99
177177
}
178178
```
179179

0 commit comments

Comments
 (0)