Kotlin语言学习笔记(2)

时间:2022-09-03 19:46:22

类(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. 坎坷路:ASP&period;NET 5 Identity 身份验证(上集)

    之所以为上集,是因为我并没有解决这个问题,写这篇博文的目的是纪录一下我所遇到的问题,以免自己忘记,其实已经忘了差不多了,写的过程也是自己回顾的过程,并且之前收集有关 ASP.NET 5 身份验证的书签 ...

  2. swift初体验

    swift是一门类型安全的语言,同样也是基于c语言 那么c语言的一些类型也是实用的,不同的是:swift声明变量和常量是不一样的 let:用来修饰常量:var用来修饰变量 e.g: let num=1 ...

  3. 第一篇博文,整理一下关于Mac下安装本地LNMP环境的一些坑

    安装的主要步骤是按照以下这篇文章进行的http://blog.csdn.net/w670328683/article/details/50628629,但是依然遇到了一些大大小小的坑(一个环境搞了一天 ...

  4. Windows2008 Patching&lpar;打补丁&rpar;

    我们都知道Windows的服务器都需要打补丁的,要不然漏洞那个叫多啊.Windows的系列服务器打补丁无非就是两种方法: 1. 通过Internet打补丁: Go to control Panel-& ...

  5. 使用VERT&period;X构建分布式企业级应用

    谈到企业应用,就得谈分布式.低耦合.模块化.面向服务.可扩展性等等.早些时候的技术有CORBA和EJB,后面兴起的有WebService和MDB.但是这些技术不是学习.开发门槛高就是不那么轻量化.我现 ...

  6. Inheritance - SGU 129(线段与多边形相交的长度)

    题目大意:给一个凸多边形(点不是按顺序给的),然后计算给出的线段在这个凸多边形里面的长度,如果在边界不计算. 分析:WA2..WA3...WA4..WA11...WA的无话可说,总之细节一定考虑清楚, ...

  7. Uva10562——Undraw the Trees

    上来一看感觉难以下手,仔细想想就是dfs啊!!!! #include <cstdio> #include<iostream> #include<iomanip> # ...

  8. DELPHI之崩溃地址排错代码查看 转

    http://www.cnblogs.com/enli/archive/2009/01/15/1376540.html 最近研究了一下HOOK技术,想抓取某些游戏的包,因此需要注入DLL,结果老是有异 ...

  9. idea 搜索不到前端的ajax controller接口的原因

    这是因为我把 web 目录设置成了 Excluded ,没有索引所以找不到了 参考: https://www.cnblogs.com/kinome/p/9991022.html IDEA 出现 upd ...

  10. iOS 11 Xcode 开发包SDK

    一不小心,手机又升级了,哎