类(classes)

// 类声明
class Invoice {
}
// 空的类
class Empty
// 主体构造器(primary constructor)
class Person constructor(firstName: String) {
}
// 省略了关键字的主体构造器
class Person(firstName: String) {
}
// 主体构造器的代码必须写在init(初始化)代码块里面
class Customer(name: String) {
init {
logger.info("Customer initialized with value ${name}")
}
}
// 属性
class Customer(name: String) {
val customerKey = name.toUpperCase()
}
// 主体构造器里包含多个属性
class Person(val firstName: String, val lastName: String, var age: Int) {
// ...
}
// 带注解和访问权限的主体构造器
class Customer public @Inject constructor(name: String) { ... }
// 从属构造器(secondary constructor)
class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}
// 从属构造器调用主体构造器
class Person(val name: String) {
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}
// 无法创建实例的类,因为主体构造器被声明为私有访问权限
class DontCreateMe private constructor () {
}
// 具有缺省值参数的主体构造器
class Customer(val customerName: String = "")
// 生成类的实例不需要new
val invoice = Invoice()
val customer = Customer("Joe Smith")

继承(inheritance)

注意类和类中的方法在Kotlin语言中缺省不可继承,需要被继承的类和方法必须使用open关键字。

而接口和接口中的方法缺省可继承,不需要open关键字。

// 隐式继承自Any
class Example
// open表示可继承
// 子类主体构造器调用基类主体构造器
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 Base {
open fun v() {}
fun nv() {}
}
class Derived() : Base() {
override fun v() {}
}
// 覆盖基类的方法但子类不可继承
open class AnotherDerived() : Base() {
final override fun v() {}
}
// 覆盖基类的属性
open class Foo {
open val x: Int get { ... }
}
class Bar1 : Foo() {
override val x: Int = ...
}
// 在主体构造器中覆盖接口中的属性
interface Foo {
val count: Int
}
class Bar1(override val count: Int) : Foo
class Bar2 : Foo {
override var count: Int = 0
}
// 使用特殊语法解决接口的多重继承问题
// 接口中的方法都是open,即可继承的
open class A {
open fun f() { print("A") }
fun a() { print("a") }
}
interface B {
fun f() { print("B") }
fun b() { print("b") }
}
class C() : A(), B {
override fun f() {
super<A>.f() // 调用 A.f()
super<B>.f() // 调用 B.f()
}
}
// 继承基类的方法但不提供实现,子类仍然可以是抽象类
open class Base {
open fun f() {}
}
abstract class Derived : Base() {
override abstract fun f()
}

属性(properties)

// 属性声明
class Address {
var name: String = ...
var street: String = ...
var city: String = ...
var state: String? = ...
var zip: String = ...
}
// 属性访问
fun copyAddress(address: Address): Address {
val result = Address()
result.name = address.name
result.street = address.street
// ...
return result
}
// 可读可写属性
var allByDefault: Int?
var initialized = 1
// 只读属性
val simple: Int?
val inferredType = 1
// 只读属性 自定义getter
val isEmpty: Boolean
get() = this.size == 0
// 可读可写属性 自定义getter setter
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value)
}
// 属性类型自动推导
val isEmpty get() = this.size == 0
// setter为公有但getter为私有
var setterVisibility: String = "abc"
private set
// setter带注解
var setterWithAnnotation: Any? = null
@Inject set
// 通过field标识符访问属性背后的字段(backing fields)
var counter = 0
set(value) {
if (value >= 0) field = value
}
// 公有属性以及背后的私有属性(backing properties)
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
get() {
if (_table == null) {
_table = HashMap()
}
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()
}
}

接口(interfaces)

// 接口中的方法可以有缺省实现
interface MyInterface {
fun bar()
fun foo() {
// ...
}
}
// 在类中实现接口的方法
class Child : MyInterface {
override fun bar() {
// ...
}
}
// 在类中实现接口的属性
interface MyInterface {
val prop: Int
val propertyWithImplementation: String
get() = "foo"
fun foo() {
print(prop)
}
}
class Child : MyInterface {
override val prop: Int = 29
}
// 使用特殊语法解决接口的多重继承问题
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()
}
}

可见性修饰符(visibility modifiers)

这个术语太怪癖,其实就是其他语言中的访问权限。

一共四种可见性(访问权限):

  • private: 类或文件内可见
  • protected: private的可见性加上子类可见
  • internal: 模块内可见
  • public: 到处可见

局部的变量,类以及函数没有可见性。

模块是指物理上的模块(IntelliJ IDEA模块,maven和gradle工程等)

// 文件示例
// 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),内部使用 this 指代调用方对象
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
}
val l = mutableListOf(1, 2, 3)
l.swap(0, 2)
// 静态分发(dispatched statically)
open class C
class D: C()
fun C.foo() = "c"
fun D.foo() = "d"
fun printFoo(c: C) {
println(c.foo())
}
printFoo(D()) // 输出 c
// 同名时成员函数优先
class C {
fun foo() { println("member") }
}
fun C.foo() { println("extension") }
c.foo() // member
// 可以重载成员函数
class C {
fun foo() { println("member") }
}
fun C.foo(i: Int) { println("extension") }
C().foo(1) // extension
// 扩展可空类型
fun Any?.toString(): String {
if (this == null) return "null"
return toString()
}
// 扩展属性(extension properties)
val <T> List<T>.lastIndex: Int
get() = size - 1
// 扩展伴生对象(companion object)
class MyClass {
companion object { } // will be called "Companion"
}
fun MyClass.Companion.foo() {
// ...
}
// 扩展与包的关系
package foo.bar
fun Baz.goo() { ... }
//
package com.example.usage
import foo.bar.goo
import foo.bar.*
fun usage(baz: Baz) {
baz.goo()
}
// 分发接收者(dispatch receiver)及扩展接收者(extension receiver)
class D {
fun bar() { ... }
}
class C {
fun baz() { ... }
fun D.foo() {
bar() // calls D.bar
baz() // calls C.baz
}
fun caller(d: D) {
d.foo() // call the extension function
}
}
// 扩展接收者优先于分发接收者
class C {
fun D.foo() {
toString() // calls D.toString()
this@C.toString() // calls C.toString()
}
}
// 分发接收者有多态,扩展接收者没有多态
open class D {
}
class D1 : D() {
}
open class C {
open fun D.foo() {
println("D.foo in C")
}
open fun D1.foo() {
println("D1.foo in C")
}
fun caller(d: D) {
d.foo()
}
}
class C1 : C() {
override fun D.foo() {
println("D.foo in C1")
}
override fun D1.foo() {
println("D1.foo in C1")
}
}
C().caller(D()) // prints "D.foo in C"
C1().caller(D()) // prints "D.foo in C1" - dispatch receiver is resolved virtually
C().caller(D1()) // prints "D.foo in C" - extension receiver is resolved statically

Kotlin语言学习笔记(2)的更多相关文章

  1. Kotlin语言学习笔记(1)

    fun main(args: Array<String>) { println("Hello, World!") } 基本语法 声明常量用val,声明变量用var,声明 ...

  2. Kotlin语言学习笔记(6)

    运算符重载(Operator overloading) 一元运算符 Expression Translated to +a a.unaryPlus() -a a.unaryMinus() !a a.n ...

  3. Kotlin语言学习笔记(5)

    委托模式(Delegation) 类的委托 interface Base { fun print() } class BaseImpl(val x: Int) : Base { override fu ...

  4. Kotlin语言学习笔记(3)

    数据类(Data Classes) data class User(val name: String, val age: Int) 编译器自动生成的有: equals()/hashCode() toS ...

  5. Kotlin语言学习笔记(7)

    反射 // 反射 val c = MyClass::class val c2 = MyClass::class.java // 获取KClass的引用 val widget: Widget = ... ...

  6. Kotlin语言学习笔记(4)

    函数 // 函数定义及调用 fun double(x: Int): Int { return 2*x } val result = double(2) // 调用方法 Sample().foo() / ...

  7. HTML语言学习笔记(会更新)

    # HTML语言学习笔记(会更新) 一个html文件是由一系列的元素和标签组成的. 标签: 1.<html></html> 表示该文件为超文本标记语言(HTML)编写的.成对出 ...

  8. 2017-04-21周C语言学习笔记

    C语言学习笔记:... --------------------------------- C语言学习笔记:学习程度的高低取决于.自学能力的高低.有的时候生活就是这样的.聪明的人有时候需要.用笨的方法 ...

  9. 2017-05-4-C语言学习笔记

    C语言学习笔记... ------------------------------------ Hello C语言:什么是程序:程序是指:完成某件事的既定方式和过程.计算机中的程序是指:为了让计算机执 ...

随机推荐

  1. [UE4]扔枪后捡枪:Get Overlapping Actors

    一.搜索碰撞体是否碰撞到枪,使用Get Overlapping Actors,只搜索Class Filter设置的对象类型.Get Overlapping Actors没有Class Filter参数 ...

  2. linux 安装scala

    1. 下载scala 到scala官网下载scala https://www.scala-lang.org/download/,目前最新版本是2.12.8 wget https://downloads ...

  3. Linux使用NFS服务实现远程共享

    首先安装 apt install -y nfs-kernel-server nfs-common 编辑配置文件 vim /etc/exports 添加内容: /root/test *(rw,sync, ...

  4. C# 中使用锁防止多线程冲突

    在编程的时候经常会用到多线程,有时候如果多线程操作同一个资源就会导致冲突,.NET提供了多种方法来防止冲突发生,这里讲下Mutex 该类位于System.Threading命名空间,常用的方式是这样: ...

  5. linux设置服务器时间同步

    yum install -y rdate 服务器请设置 */5 * * * * /usr/bin/rdate -s time-b.nist.gov ubuntu 设定时区:dpkg-reconfigu ...

  6. es6(13)--Promise

    //Promise { //原始方法 let ajax=function(callback){ console.log('执行') setTimeout(function(){ callback&am ...

  7. day4作业(基本运算流程if for)

    #coding:utf-8'''默写: 循环嵌套 必做: 1. 求1-100的所有数的和 2. 输出 1-100 内的所有奇数 3. 输出 1-100 内的所有偶数 5. 求1-2+3-4+5 ... ...

  8. v修 pp改n属性

    通过修改DNS达到不FQ也能访问Google(仅限于Google)   一.前言 不知道各位小伙伴们现在用的搜索引擎是用Google搜索还是百度搜索呢?但我个人还是比较极力推荐用Google搜索的,首 ...

  9. 关于chrome控制台警告:Synchronous XMLHttpRequest on the main thread

    Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to th ...

  10. WPF 我的初学必备技能

    0.控件 0.1.内容控件(Content Controls) 0.2.条目控件(Items Controls) 0.3.文本控件(Text Controls) 0.4.范围控件(Range Cont ...