zwvista

导航

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
*/

posted on 2017-05-29 04:40  zwvista  阅读(403)  评论(0编辑  收藏  举报