Week4
Week4
一. Properties
1. Properties
1) Read-only & mutable properties
Kotlin | Java |
---|---|
property | Field + accessor(s) |
val | Filed + getter |
var | Filed + getter+setter |
Sample :
1 | // Java |
1 | // Kotlin |
2) Backing field might be absent
Kotlin | Java |
---|---|
property | accessor(s) |
val | getter |
var | getter+setter |
Sample :
1 | // Java |
1 | // Kotlin |
3) Stored value or not?
1 | // the value is stored |
4) Field
You can access
field
only inside accessors1
2
3
4
5
6
7
8
9
10class StateLogger {
var state = false
set(value) {
println(
"state has changed: " +
"$field -> $value"
)
field = value
}
}No backing field will be generated if you define accessors (custom getter and setter) and don’t use a field keyword
1
2
3
4
5
6
7
8
9enum class State { ON, OFF }
class StateLogger {
private var boolState = false
var state: State
get() = if (boolState) ON else OFF
set(value: State) {
boolState = value == ON
}
}
5) Default accessors
1 | class A { |
You can always use property instead of getter or setter (Under the hood, getter and setter will be called)
And inside the class, optimization performed by the compiler are possible (using the filed directly, but only with the trial/default case)
6) Change visibility of a setter
You want a var mutable property to be accessible only as a read-only property outside of the class
1
2
3
4
5
6
7
8class LengthCounter {
var counter: Int = 0
private set
fun addWord(word: String) {
counter += word.length
}
}
2. More about properties
1) override property
2) Smart cast
3. Lazy and late initialization
1) by lazy
1 | val value:String = run { |
2) lateinit
1 | // lateinit is still unsafe and a runtime exception may be thrown, but with a detailed message |
二. Object-oriented Programming
1. OOP in Kotlin
1) modifier intro.
Modifier | Description |
---|---|
final (default) |
cann’t be overridden |
open |
can be overridden |
abstract |
must be overridden |
override (mandatory) |
Overrides a member in a superclass or interface |
Visibility Modifier | Class member | Top-level declaration |
---|---|---|
public (default) |
visible everywhere | visible everywhere |
internal |
visible in the mudule | visible in the module |
protected |
visible in the class and the subclasses (in Java, it includes the same package) | |
private |
visible in the class | visible in the file |
Visibility modifiers and Java
Kotlin modifier JVM level public
public
internal
public & name mangling
protected
protected
private
private
/package private
2) Package structure
1 | // Java |
- one kotlin file may contain several classes and top-level functions
2. Constructors, Inheritance syntax
1) Constructor
Primer Constructor
var/val on a parameter creates a property
1
2
3class Person(val name: String) {
}the same as
1
2
3
4
5
6class Person(name: String){
val name:String
init {
this.name = name
}
}Changing visibility of a constructor
1
2class InternalComponent
internal constructor(name:St)Each Secondary constructor must using this to call another constructor
2) Syntax for inheritance
Same syntax for extends and implements
1
2
3
4
5interface Base
class BaseImpl : Base
open class Parent
class Child: Parent()1
2open class Parent(val name: String)
class Child(name: String) : Parent(name)1
2
3
4open class Parent(val name: String)
class Child : Parent {
constructor(name: String, param: Int) : super(name)
}init order
1
2
3
4
5
6
7
8
9
10
11
12
13
14open class Parent(){
init {
println("Parent")
}
}
class Child:Parent(){
init {
println("Child")
}
}
val child = Child()
// Parent
// ChildOverriding a property
Actually you are overriding a getter, not a field
1
2
3
4
5
6
7
8
9
10
11
12
13
14open class Parent() {
open val foo = 1
init {
println(foo)
}
}
class Child : Parent() {
override val foo = 2
}
val child = Child()
// 0
3. Class modifiers
1) enum
enum class Color(val r: Int, val g: Int, val b: Int) { BLUE(0, 0, 255), ORANGE(255, 165, 0), RED(255, 0, 0); fun rgb() = (r * 256 + g) * 256 + b } fun main(){ println(BLUE.r) // 0 println(BLUE.rgb()) // 255 } <!--code20-->
1 | sealed class Expr |
4) nested and inner class
- Inner class stores the reference to an outer class (Memory leak)
In Java | In Kotlin | Class declared within another class |
---|---|---|
static class A | class A (by default) | nested class |
class A (by default) | inner class A | inner class |
1 | class A { |
1 | class A { |
5) Class delegation
To implement the interface by delegation to this instance using keyword by
1 | interface Repository { |
4. ?? Objects, object expressions & companion objects
5. Constants
const (for primitive types and String)
compile-time constants, the value is inlined
1
const val answer = 42
@JvmField (eliminates accessors)
exposes a Kotlin property as a field in Java
@JvmStatic @JvmField const
1
2
3
4
5
6
7
8
9object SuperComputer{
val answer = 42
}
fun main(){
println(SuperComputer.answer)
// System.out.println(SuperComputer.getAnswer())
}1
2
3
4
5
6
7
8
9object SuperComputer{
val answer = 42
}
fun main(){
println(SuperComputer.answer)
// System.out.println(SuperComputer.answer)
}1
2
3
4
5
6
7
8object SuperComputer{
const val answer = 42
}
fun main(){
println(SuperComputer.answer)
// System.out.println(42)
}
6. Generics
T can be nullable or not nullable
1
2
3
4
5
6
7
8
9
10fun <T> List<T>.filter(predicate:(T) -> Boolean):List<T> {
return this
}
fun use1(ints:List<Int>){
ints.filter { it > 0 }
}
fun use2(strings:List<String?>){
strings.filter { !it.isNullOrEmpty() }
}Nullable generic argument
1
2
3
4
5
6
7
8fun <T> List<T>.firstOrNull(): T? {
...
}
val ints = listOf(1, 2, 3)
val i = ints.firstOrNull() // 1
val j = listOf<Int>().firstOrNull() // null
val k = listOf(null, 1).firstOrNull() // nullNon-nullable upper bound (
Any
)1
2
3
4
5
6
7fun <T : Any> foo(list: List<T>) {
for (element in list) {
}
}
//val a = foo(listOf(1,null)) // compile errorNullable upper bound (
Any?
)Comparable upper bound
Multiple constraints for a type parameter (using
where
)1
2
3
4
5
6fun <T> ensureTrailingPeriod(seq: T)
where T : CharSequence, T : Appendable{
if (!seq.endsWith('.')){
seq.append('.')
}
}same JVM signature problem
1
2// fun List<Int>.average(): Double {}
// fun List<Double>.average(): Double {}Solution
1
2
3fun List<Int>.average(): Double {}
fun List<Double>.average(): Double {}
三. Conventions
1. Operator Overloading
1) Arithmetic operations
expression | function name |
---|---|
a + b | plus |
a - b | minus |
a * b | times |
a / b | div |
a % b | mod |
1 | operator fun Point.plus(other: Point): Point { |
2) No restrictions on parameter type
1 | operator fun Point.times(scale: Int): Point { |
3) Unary operation
1 | operator fun Point.unaryMinus() = Point(-x,-y) |
Expression | function name |
---|---|
+a | unaryPlus |
-a | unaryMinus |
!a | not |
++a,a++ | inc |
–a,a– | dec |
4) Assignment operations
a += b
it you define any one of the 2, it will call the defined one,
else if you define 2, you will call a.plusAssign if a is val,
else you will get a compile error
a = a.plus(b)
a.plusAssign(b)
5) Conventions for lists
- Prefer
val
tovar
1 | var l1 = listOf(1, 2) |
2. Conventions
1) Comparisons
symbol | translated to |
---|---|
a > b | a.compareTo(b) > 0 |
a < b | a.compareTo(b) < 0 |
a >= b | a.compareTo(b) >= 0 |
a <= b | a.compareTo(b) <= 0 |
2) Equality check
s1 == s2
calls equals under the hoods1.equals(s2)
it can correctly handles nullable values
1
2
3s1 == s2 // s1.equals(s2)
null == "abc" // false
null == null // true
3) Index
Accessing elements by index: []
x[a,b] // x.get(a,b)
y[a,b] = c // x.set(a,b,c)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Board() {
val cheet = Array(3) { CharArray(2) }
operator fun get(x: Int, y: Int): Char {
return cheet[x][y]
}
operator fun set(x: Int, y: Int, value: Char) {
cheet[x][y] = value
}
}
fun main() {
val board = Board()
board[1, 2] = 'x'
board[1, 2] // 'x'
}
4) Other convention
symbol | translated to |
---|---|
a in c |
c.contains(a) |
start..end |
start.rangeTo(end) |
for(a in c){} (in a for loop) |
c.iterator() |
Destructuring declarations
val (a,b) = p
- val a = p.component1()
- val b = p.component2()
Destructuring in lambdas
Description Syntax One parameter { a -> …} Two parameters { a, b -> …} A destructured pair { (a, b) -> …} A destructured pair and another parameter { (a, b), c -> …} Iterating over list with index
1
2
3for ((index, element) in list.withIndex()) {
println("$index $element")
}1
2
3
4
5for (indexedValue in list.withIndex()) {
val index = indexedValue.component1()
val element = indexedValue.component2()
println("$index $element")
}Destructuring declarations & Data classes
1
2
3
4
5
6
7
8
9
10
11
12
13
14data class Contact(
val name: String,
val email: String,
val phoneNumber: String
)
fun main() {
val contact = Contact("Kyle", "[email protected]", "185")
contact.component1()
contact.component2()
contact.component3()
val (name,_,phoneNumber) = contact
}