Kotlin语言学习笔记(3)
数据类(Data Classes)
data class User(val name: String, val age: Int)
编译器自动生成的有:
- equals()/hashCode()
- toString() 形式为 "User(name=John, age=42)"
- componentN() 函数
- copy() 函数
数据类必须符合以下条件。
- 主体构造器必须至少有一个参数。
- 所有主体构造器的参数都必须被标注为var或val。
- 数据类不可以是 abstract, open, sealed 或 inner。
// 缺省参数的例子。
data class User(val name: String = "", val age: Int = 0)
// 自动生成的copy函数。
// fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
// 实际应用copy函数的代码
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)
// 数据类与解构
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"
标准数据类包括Pair和Triple。
密封类(Sealed Classes)
密封类对继承有所限制。
密封类可以有子类,但是必须在同一文件中。
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
密封类的子类的子类不必在同一文件中。
使用密封类的好处在于在when表达式中可以处理所有情况,不必用else。
fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
// the `else` clause is not required because we've covered all the cases
}
嵌套类(Nested Classes)
// 嵌套类
class Outer {
private val bar: Int = 1
class Nested {
fun foo() = 2
}
}
val demo = Outer.Nested().foo() // == 2
// 内部类(Inner Classes)
class Outer {
private val bar: Int = 1
inner class Inner {
fun foo() = bar
}
}
val demo = Outer().Inner().foo() // == 1
// 匿名内部类(Anonymous Inner Classes)
window.addMouseListener(object: MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
override fun mouseEntered(e: MouseEvent) {
// ...
}
})
// 函数型接口的对象生成
val listener = ActionListener { println("clicked") }
枚举类(Enum Classes)
每个枚举常量都是一个对象。
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
// 初始化
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}
// 枚举类内部的匿名类
// 在枚举类你内定义抽象方法
// 然后使用枚举对象的匿名类来实现抽象方法
// 这里需要使用分号隔开枚举对象的定义和抽象方法的定义
enum class ProtocolState {
WAITING {
override fun signal() = TALKING
},
TALKING {
override fun signal() = WAITING
};
abstract fun signal(): ProtocolState
}
// 使用枚举常量
// EnumClass.valueOf(value: String): EnumClass
// EnumClass.values(): Array<EnumClass>
// enumValues<T>()
// enumValueOf<T>()
enum class RGB { RED, GREEN, BLUE }
inline fun <reified T : Enum<T>> printAllValues() {
print(enumValues<T>().joinToString { it.name })
}
printAllValues<RGB>() // prints RED, GREEN, BLUE
// 每个枚举常量都有如下属性
val name: String
val ordinal: Int
// 枚举类都实现了Comparable接口
对象表达式(Object Expressions)
对象表达式扩展了Java中的匿名内部类。
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
override fun mouseEntered(e: MouseEvent) {
// ...
}
})
// 构造器带参数的类也能使用对象表达式
open class A(x: Int) {
public open val y: Int = x
}
interface B {...}
val ab: A = object : A(1), B {
override val y = 15
}
// 使用对象表达式可以达成匿名类(对象)的效果
fun foo() {
val adHoc = object {
var x: Int = 0
var y: Int = 0
}
print(adHoc.x + adHoc.y)
}
// 匿名对象只能用于local和private声明
// 如果用于public声明,则成员不可访问
class C {
// Private function, so the return type is the anonymous object type
private fun foo() = object {
val x: String = "x"
}
// Public function, so the return type is Any
fun publicFoo() = object {
val x: String = "x"
}
fun bar() {
val x1 = foo().x // Works
val x2 = publicFoo().x // ERROR: Unresolved reference 'x'
}
}
// 对象表达式中的方法可以访问外层变量(不仅限于final变量)
fun countClicks(window: JComponent) {
var clickCount = 0
var enterCount = 0
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
clickCount++
}
override fun mouseEntered(e: MouseEvent) {
enterCount++
}
})
// ...
}
对象声明(Object declarations)
使用对象声明可以方便的声明单件(Singleton)。
在类中使用对象声明可以声明类的伴生对象(Companion object)。
伴生对象中声明的方法相当于其他语言的静态方法。
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
// ...
}
val allDataProviders: Collection<DataProvider>
get() = // ...
}
// 使用单件
DataProviderManager.registerDataProvider(...)
// 有基类的情况
object DefaultListener : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
override fun mouseEntered(e: MouseEvent) {
// ...
}
}
// 类的伴生对象,用于实现静态方法
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
// 使用伴生对象的方法(相当于静态方法)
val instance = MyClass.create()
// 使用伴生对象自身
class MyClass {
companion object {
}
}
val x = MyClass.Companion
// 伴生对象可以实现接口
interface Factory<T> {
fun create(): T
}
class MyClass {
companion object : Factory<MyClass> {
override fun create(): MyClass = MyClass()
}
}
对象表达式和对象声明的语义
- 对象表达式是贪婪的(使用时即刻生成)。
- 对象声明是懒惰的 (第一次访问时生成)。
- 伴生对象在相应的类被生成时生成。
Kotlin语言学习笔记(3)的更多相关文章
- Kotlin语言学习笔记(2)
类(classes) // 类声明 class Invoice { } // 空的类 class Empty // 主体构造器(primary constructor) class Person co ...
- Kotlin语言学习笔记(1)
fun main(args: Array<String>) { println("Hello, World!") } 基本语法 声明常量用val,声明变量用var,声明 ...
- Kotlin语言学习笔记(6)
运算符重载(Operator overloading) 一元运算符 Expression Translated to +a a.unaryPlus() -a a.unaryMinus() !a a.n ...
- Kotlin语言学习笔记(5)
委托模式(Delegation) 类的委托 interface Base { fun print() } class BaseImpl(val x: Int) : Base { override fu ...
- Kotlin语言学习笔记(7)
反射 // 反射 val c = MyClass::class val c2 = MyClass::class.java // 获取KClass的引用 val widget: Widget = ... ...
- Kotlin语言学习笔记(4)
函数 // 函数定义及调用 fun double(x: Int): Int { return 2*x } val result = double(2) // 调用方法 Sample().foo() / ...
- HTML语言学习笔记(会更新)
# HTML语言学习笔记(会更新) 一个html文件是由一系列的元素和标签组成的. 标签: 1.<html></html> 表示该文件为超文本标记语言(HTML)编写的.成对出 ...
- 2017-04-21周C语言学习笔记
C语言学习笔记:... --------------------------------- C语言学习笔记:学习程度的高低取决于.自学能力的高低.有的时候生活就是这样的.聪明的人有时候需要.用笨的方法 ...
- 2017-05-4-C语言学习笔记
C语言学习笔记... ------------------------------------ Hello C语言:什么是程序:程序是指:完成某件事的既定方式和过程.计算机中的程序是指:为了让计算机执 ...
随机推荐
- [UE4]蓝图:重写父类时调用父类方法
右键重写的方法选择“Add call to parent function” 一定要善用这个功能,实现原有父类功能的同时实现子类特别的功能.
- Android 运行时报错Error running app: Instant Run requires 'Tools | Android | Enable ADB integration' to be enabled. 的解决办法
解决方法:在菜单栏,Tools->Android->Enable ADB integration勾选就可以了.
- list函数
列表的切片: 获取: 1. [start:] 2. [:end] 3. [statr:end] 4. [statr: end: spet] 修改: listvar[:2] = ' 把0~1索引元素删除 ...
- 多线程Task
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- 通过 SSH 转发TCP连接数据
设定 首先双方的/etc/ssh/sshd_config设定以下四项: AllowAgentForwarding yes AllowTcpForwarding yes GatewayPorts yes ...
- 「NOI2018」屠龙勇士(CRT)
/* 首先杀每条龙用到的刀是能够确定的, 然后我们便得到了许多形如 ai - x * atki | pi的方程 而且限制了x的最小值 那么exgcd解出来就好了 之后就是扩展crt合并了 因为全T调了 ...
- 关于python无法显示中文的问题:SyntaxError: Non-ASCII character '\xe4' in file test.py on line 3, but no encoding declared。
[已解决]关于python无法显示中文的问题:SyntaxError: Non-ASCII character '\xe4' in file test.py on line 3, but no enc ...
- 【powerBI】power pivot添加参数表
背景 最近在做应用分析,爬了几个应用市场的排行榜,需要分析前多少名各个品类的app有多少个.数据量不大,excel就能做分析,所以想起来pivot的参数表功能.这个功能还是比较实用的,在这再做个记录, ...
- [多线程]多线程(Thread、Runnable、Callable)
1.继承Thread类,重写run方法 线程 是程序中的执行线程.Java 虚拟机允许应用程序并发地运行多个执行线程. 每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程.每个线程都可以或不 ...
- hive数据倾斜原因以及解决办法
何谓数据倾斜?数据倾斜指的是,并行处理的数据集 中,某一部分(如Spark的一个Partition)的数据显著多于其它部分,从而使得该部分的处理速度成为整个数据集处理的瓶颈. 表现为整体任务基本完成, ...