Kotlin语言学习笔记(2)
类(classes)
// 类声明
class Person { /*...*/ }
// 空的类
class Empty
// 主体构造器(primary constructor)
class Person constructor(firstName: String) { /*...*/ }
// 省略了关键字的主体构造器
class Person(firstName: String) { /*...*/ }
// 主体构造器的代码必须写在init(初始化)代码块里面
// 可以存在不止一个初始化代码块。这些代码块将按序来执行。
class InitOrderDemo(name: String) {
val firstProperty = "First property: $name".also(::println)
init {
println("First initializer block that prints $name")
}
val secondProperty = "Second property: ${name.length}".also(::println)
init {
println("Second initializer block that prints ${name.length}")
}
}
/*
First property: hello
First initializer block that prints hello
Second property: 5
Second initializer block that prints 5
*/
// 属性
class Customer(name: String) {
val customerKey = name.toUpperCase()
}
// 主体构造器里可以声明多个属性
class Person(val firstName: String, val lastName: String, var age: Int)
// 主体构造器里声明的属性可以有缺省值
class Person(val firstName: String, val lastName: String, var isEmployed: Boolean = true)
// 主体构造器里声明的属性可以有拖尾逗号
class Person(
val firstName: String,
val lastName: String,
var age: Int, // trailing comma
) { /*...*/ }
// 带注解和访问权限的主体构造器
class Customer public @Inject constructor(name: String) { /*...*/ }
// 从属构造器(secondary constructor)
class Person(val pets: MutableList<Pet> = mutableListOf())
class Pet {
constructor(owner: Person) {
owner.pets.add(this) // adds this pet to the list of its owner's pets
}
}
// 从属构造器调用主体构造器(必须使用 this 关键字)
class Person(val name: String) {
val children: MutableList<Person> = mutableListOf()
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}
// 主体构造器的代码在从属构造器的代码之前执行
class Constructors {
init {
println("Init block")
}
constructor(i: Int) {
println("Constructor $i")
}
}
/*
Init block
Constructor 1
*/
// 无法创建实例的类,因为主体构造器被声明为私有访问权限
class DontCreateMe private constructor() { /*...*/ }
// 生成类的实例不需要new
val invoice = Invoice()
val customer = Customer("Joe Smith")
// 抽象类
abstract class Polygon {
abstract fun draw()
}
class Rectangle : Polygon() {
override fun draw() {
// draw the rectangle
}
}
// 抽象类继承非抽象类
open class Polygon {
open fun draw() {
// some default polygon drawing method
}
}
abstract class WildShape : Polygon() {
// Classes that inherit WildShape need to provide their own
// draw method instead of using the default on Polygon
abstract override fun draw()
}
继承(inheritance)
注意类和类中的方法在Kotlin语言中缺省不可继承,需要被继承的类和方法必须使用open关键字。
而接口和接口中的方法缺省可继承,不需要open关键字。
// 隐式继承自Any
class Example // Implicitly inherits from Any
// open表示可继承
open class Base // Class is open for inheritance
// 子类主体构造器调用基类主体构造器
open class Base(p: Int)
class Derived(p: Int) : Base(p)
// 子类从属构造器调用基类的构造器
class MyView : View {
constructor(ctx: Context) : super(ctx)
constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}
// 覆盖基类的方法
open class Shape {
open fun draw() { /*...*/ }
fun fill() { /*...*/ }
}
class Circle() : Shape() {
override fun draw() { /*...*/ }
}
// 覆盖基类的方法但子类不可继承
open class Rectangle() : Shape() {
final override fun draw() { /*...*/ }
}
// 覆盖基类的属性
open class Shape {
open val vertexCount: Int = 0
}
class Rectangle : Shape() {
override val vertexCount = 4
}
// 在主体构造器中覆盖接口中的属性
interface Shape {
val vertexCount: Int
}
class Rectangle(override val vertexCount: Int = 4) : Shape // Always has 4 vertices
class Polygon : Shape {
override var vertexCount: Int = 0 // Can be set to any number later
}
// 基类的初始化代码在子类的初始化代码之前执行
open class Base(val name: String) {
init { println("Initializing a base class") }
open val size: Int =
name.length.also { println("Initializing size in the base class: $it") }
}
class Derived(
name: String,
val lastName: String,
) : Base(name.replaceFirstChar { it.uppercase() }.also { println("Argument for the base class: $it") }) {
init { println("Initializing a derived class") }
override val size: Int =
(super.size + lastName.length).also { println("Initializing size in the derived class: $it") }
}
/*
Constructing the derived class("hello", "world")
Argument for the base class: Hello
Initializing a base class
Initializing size in the base class: 5
Initializing a derived class
Initializing size in the derived class: 10
*/
// 使用 super 关键字调用基类的代码
open class Rectangle {
open fun draw() { println("Drawing a rectangle") }
val borderColor: String get() = "black"
}
class FilledRectangle : Rectangle() {
override fun draw() {
super.draw()
println("Filling the rectangle")
}
val fillColor: String get() = super.borderColor
}
// 内部类调用外部类的基类的代码
class FilledRectangle: Rectangle() {
override fun draw() {
val filler = Filler()
filler.drawAndFill()
}
inner class Filler {
fun fill() { println("Filling") }
fun drawAndFill() {
super@FilledRectangle.draw() // Calls Rectangle's implementation of draw()
fill()
println("Drawn a filled rectangle with color ${super@FilledRectangle.borderColor}") // Uses Rectangle's implementation of borderColor's get()
}
}
}
/*
Drawing a rectangle
Filling
Drawn a filled rectangle with color black
*/
// 使用特殊语法解决接口的多重继承问题
// 接口中的方法都是open,即可继承的
open class Rectangle {
open fun draw() { /* ... */ }
}
interface Polygon {
fun draw() { /* ... */ } // interface members are 'open' by default
}
class Square() : Rectangle(), Polygon {
// The compiler requires draw() to be overridden:
override fun draw() {
super<Rectangle>.draw() // call to Rectangle.draw()
super<Polygon>.draw() // call to Polygon.draw()
}
}
属性(properties)
// 属性声明
class Address {
var name: String = "Holmes, Sherlock"
var street: String = "Baker"
var city: String = "London"
var state: String? = null
var zip: String = "123456"
}
// 属性访问
fun copyAddress(address: Address): Address {
val result = Address() // there's no 'new' keyword in Kotlin
result.name = address.name // accessors are called
result.street = address.street
// ...
return result
}
// 可读可写属性
var initialized = 1 // has type Int, default getter and setter
// var allByDefault // ERROR: explicit initializer required, default getter and setter implied
// 只读属性
val simple: Int? // has type Int, default getter, must be initialized in constructor
val inferredType = 1 // has type Int and a default getter
// 只读属性 自定义getter
class Rectangle(val width: Int, val height: Int) {
val area: Int // property type is optional since it can be inferred from the getter's return type
get() = this.width * this.height
}
/*
Width=3, height=4, area=12
*/
// 只读属性 类型自动推导
val area get() = this.width * this.height
// 可读可写属性 自定义getter setter
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value) // parses the string and assigns values to other properties
}
// setter为公有但getter为私有
var setterVisibility: String = "abc"
private set // the setter is private and has the default implementation
// setter带注解
var setterWithAnnotation: Any? = null
@Inject set // annotate the setter with Inject
// 通过field标识符访问属性背后的字段(backing fields)
var counter = 0
set(value) {
if (value >= 0) field = value
}
// 不需要属性背后的字段
val isEmpty: Boolean
get() = this.size == 0
// 公有属性以及背后的私有属性(backing properties)
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
get() {
if (_table == null) {
_table = HashMap() // Type parameters are inferred
}
return _table ?: throw AssertionError("Set to null by another thread")
}
// 编译期常量
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }
// 需要延迟初始化的属性使用 lateinit 来修饰
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method()
}
}
// 核实确认延迟初始化的属性是否已经初始化
if (foo::bar.isInitialized) {
println(foo.bar)
}
接口(interfaces)
// 接口中的方法可以有缺省实现
interface MyInterface {
fun bar()
fun foo() {
// optional body
}
}
// 在类中实现接口的方法
class Child : MyInterface {
override fun bar() {
// body
}
}
// 在类中实现接口的属性
interface MyInterface {
val prop: Int // abstract
val propertyWithImplementation: String
get() = "foo"
fun foo() {
print(prop)
}
}
class Child : MyInterface {
override val prop: Int = 29
}
// 接口的继承
interface Named {
val name: String
}
interface Person : Named {
val firstName: String
val lastName: String
override val name: String get() = "$firstName $lastName"
}
data class Employee(
// implementing 'name' is not required
override val firstName: String,
override val lastName: String,
val position: Position
) : Person
// 使用特殊语法解决接口的多重继承问题
interface A {
fun foo() { print("A") }
fun bar()
}
interface B {
fun foo() { print("B") }
fun bar() { print("bar") }
}
class C : A {
override fun bar() { print("bar") }
}
class D : A, B {
override fun foo() {
super<A>.foo()
super<B>.foo()
}
override fun bar() {
super<B>.bar()
}
}
函数型接口(functional interfaces)
函数型接口也被称作 SAM 接口(Single Abstract Method interfaces 单一方法接口)
// 带 fun 修饰符的函数型接口
fun interface KRunnable {
fun invoke()
}
// 函数型接口可以使用内部类实现,也可以用更简洁的 lambda 来实现
fun interface IntPredicate {
fun accept(i: Int): Boolean
}
// Creating an instance of a class
val isEven = object : IntPredicate {
override fun accept(i: Int): Boolean {
return i % 2 == 0
}
}
// Creating an instance using lambda
val isEven = IntPredicate { it % 2 == 0 }
// 将传统的接口改进为函数型接口
// 传统接口
interface Printer {
fun print()
}
fun Printer(block: () -> Unit): Printer = object : Printer { override fun print() = block() }
// 函数型接口
fun interface Printer {
fun print()
}
documentsStorage.addPrinter(::Printer)
@Deprecated(message = "Your message about the deprecation", level = DeprecationLevel.HIDDEN)
fun Printer(...) {...}
// 使用类型别名来实现函数型接口相似的功能
typealias IntPredicate = (i: Int) -> Boolean
val isEven: IntPredicate = { it % 2 == 0 }
fun main() {
println("Is 7 even? - ${isEven(7)}")
}
可见性修饰符(visibility modifiers)
这个术语太怪癖,其实就是其他语言中的访问权限。
一共四种可见性(访问权限):
- private: 类中可见(在类中声明时)或文件内可见(在包内声明时)
- protected: 类和子类可见(只能在类中声明)
- internal: 模块内可见
- public: 到处可见
局部的变量,类以及函数没有可见性。
模块是指物理上的模块(IntelliJ IDEA模块,maven和gradle工程等)
// 在包内可以声明顶层的函数,属性,类和对象
// file name: example.kt
package foo
fun baz() { ... }
class Bar { ... }
// 在包内声明时
// file name: example.kt
package foo
private fun foo() {} // visible inside example.kt
public var bar: Int = 5 // property is visible everywhere
private set // setter is visible only in example.kt
internal val baz = 6 // visible inside the same module
// 在类中声明时
open class Outer {
private val a = 1
protected open val b = 2
internal val c = 3
val d = 4 // public by default
protected class Nested {
public val e: Int = 5
}
}
class Subclass : Outer() {
// a is not visible
// b, c and d are visible
// Nested and e are visible
override val b = 5 // 'b' is protected
}
class Unrelated(o: Outer) {
// o.a, o.b are not visible
// o.c and o.d are visible (same module)
// Outer.Nested is not visible, and Nested::e is not visible either
}
// 主体构造器的可见性
class C private constructor(a: Int) { ... }
扩展(extensions)
包括扩展函数,扩展属性
扩展函数可以是全局的,也可以声明在某个类或伴生对象之中
// 扩展函数(extension functions)
// 函数名前附加接收者类型(receiver type)
// 内部使用 this 指代调用方对象
fun MutableList<Int>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // 'this' corresponds to the list
this[index1] = this[index2]
this[index2] = tmp
}
val list = mutableListOf(1, 2, 3)
list.swap(0, 2) // 'this' inside 'swap()' will hold the value of 'list'
// 泛型扩展函数
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // 'this' corresponds to the list
this[index1] = this[index2]
this[index2] = tmp
}
// 静态分发(dispatched statically)
open class Shape
class Rectangle: Shape()
fun Shape.getName() = "Shape"
fun Rectangle.getName() = "Rectangle"
fun printClassName(s: Shape) {
println(s.getName())
}
printClassName(Rectangle()) // 输出 Shape
// 同名时成员函数优先
class Example {
fun printFunctionType() { println("Class method") }
}
fun Example.printFunctionType() { println("Extension function") }
Example().printFunctionType() // 输出 Class method
// 可以重载成员函数
class Example {
fun printFunctionType() { println("Class method") }
}
fun Example.printFunctionType(i: Int) { println("Extension function #$i") }
Example().printFunctionType(1) // 输出 Extension function #1
// 扩展可空类型
fun Any?.toString(): String {
if (this == null) return "null"
// after the null check, 'this' is autocast to a non-null type, so the toString() below
// resolves to the member function of the Any class
return toString()
}
// 扩展属性(extension properties)
val <T> List<T>.lastIndex: Int
get() = size - 1
// 扩展属性不可以有缺省值
val House.number = 1 // error: initializers are not allowed for extension properties
// 扩展伴生对象(companion object)
class MyClass {
companion object { } // will be called "Companion"
}
fun MyClass.Companion.printCompanion() { println("companion") }
fun main() {
MyClass.printCompanion() // 输出 companion
}
// 扩展与包的关系
// 定义方
package org.example.declarations
fun List<String>.getLongestString() { /*...*/}
// 使用方
package org.example.usage
import org.example.declarations.getLongestString
fun main() {
val list = listOf("red", "green", "blue")
list.getLongestString()
}
// 可以在一个类中定义对另一类的扩展函数
// 此时前者被称为分发接收者(dispatch receiver)
// 而后者被称为扩展接收者(extension receiver)
class Host(val hostname: String) {
fun printHostname() { print(hostname) }
}
class Connection(val host: Host, val port: Int) {
fun printPort() { print(port) }
fun Host.printConnectionString() {
printHostname() // calls Host.printHostname()
print(":")
printPort() // calls Connection.printPort()
}
fun connect() {
/*...*/
host.printConnectionString() // calls the extension function
}
}
fun main() {
Connection(Host("kotl.in"), 443).connect() // 输出 kotl.in:443
//Host("kotl.in").printConnectionString() // error, the extension function is unavailable outside Connection
}
// 扩展接收者优先于分发接收者
class Connection {
fun Host.getConnectionString() {
toString() // calls Host.toString()
this@Connection.toString() // calls Connection.toString()
}
}
// 分发接收者有多态,扩展接收者没有多态
open class Base { }
class Derived : Base() { }
open class BaseCaller {
open fun Base.printFunctionInfo() {
println("Base extension function in BaseCaller")
}
open fun Derived.printFunctionInfo() {
println("Derived extension function in BaseCaller")
}
fun call(b: Base) {
b.printFunctionInfo() // call the extension function
}
}
class DerivedCaller: BaseCaller() {
override fun Base.printFunctionInfo() {
println("Base extension function in DerivedCaller")
}
override fun Derived.printFunctionInfo() {
println("Derived extension function in DerivedCaller")
}
}
fun main() {
BaseCaller().call(Base()) // "Base extension function in BaseCaller"
DerivedCaller().call(Base()) // "Base extension function in DerivedCaller" - dispatch receiver is resolved virtually
DerivedCaller().call(Derived()) // "Base extension function in DerivedCaller" - extension receiver is resolved statically
}
/*
Base extension function in BaseCaller
Base extension function in DerivedCaller
Base extension function in DerivedCaller
*/