kotlin控制语句
if else 语句
// 传统用法
var max = a
if (a < b) max = b
// 使用 else
var max: Int
if (a > b) {
max = a
} else {
max = b
}
// 作为表达式
val max = if (a > b) a else b //类似于java中的三元运算符, kotlin中没有三元运算符
// 我们也可以把 IF 表达式的结果赋值给一个变量。
val max = if (a > b) {
print("Choose a")
a
} else {
print("Choose b")
b
}
使用区间 使用 in 运算符来检测某个数字是否在指定区间内.
//区间格式为 x..y :
val x = 5
val y = 9
if (x in 1..8) {
println("x 在区间内")
}
When 表达式 类似于Java中的switch表达式, 但是远比它强大, 支持所有数据类型
// 其最简单的形式如下:
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // 注意这个块 在打括号内可以执行多行代码
print("x 不是 1 ,也不是 2")
}
}
// 在 when 中,else 同 switch 的 default。如果其他分支都不满足条件将会求值 else 分支。
// 如果很多分支需要用相同的方式处理,则可以把多个分支条件放在一起,用逗号分隔:
when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
// 检测一个值在(in)或者不在(!in)一个区间或者集合中:
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
// 另一种可能性是检测一个值是(is)或者不是(!is)一个特定类型的值。注意: 由于智能转换,
// 你可以访问该类型的方法和属性而无需 任何额外的检测。
fun hasPrefix(x: Any) = when(x) {
// is 类似于Java中的instanceof 用来判断数据类型 和java不同的是, 使用is判断过类型后, 不用再强转数据类型,
// 可以智能转换
is String -> x.startsWith("prefix")
else -> false
}
// when 也可以用来取代 if-else if链。 如果不提供参数,所有的分支条件都是简单的布尔表达式,
// 而当一个分支的条件为真时, 则执行该分支:
when {
x.isOdd() -> print("x is odd")
x.isEven() -> print("x is even")
else -> print("x is funny")
}
for循环, for 可以循环遍历任何提供了迭代器的对象。 数组, 区间(0..10), 集合, Map等
//语法:
for (item in collection) {
print(item)
}
//通过索引遍历数组
for (i in array.indices) {
print(array[i])
}
//对集合进行遍历
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
//正常循环 1..4 或者1 until 5(不包含5)
for (i in 1..4) print(i) // 打印结果为: "1234"
//反序循环 4 downTo 1 包含头和尾
for (i in 4 downTo 1) print(i) // 打印结果为: "4321"
//也支持指定步长:关键字:step
for (i in 1..4 step 2) print(i) // 打印结果为: "13"
for (i in 4 downTo 1 step 2) print(i) // 打印结果为: "42"
while 与 do...while 循环, return, break,contine 和java一样,
//标签处返回, 稍有区别
fun foo() {//显式标签
ints.forEach lit@ {
if (it == 0) return@lit
print(it)
}
}
fun foo() {
ints.forEach {//隐式标签
if (it == 0) return@forEach
print(it)
}
}
类和对象
类定义
class Person { //默认public权限 // 大括号内是类体构成 }
定义一个空类
class Empty
在类中定义成员函数:
class Runoob() { fun foo() { print("Foo") } // 成员函数 }
属性定义
class Person{
var name: String = "wwf" //默认public
private var age: Int= 12//私有的属性
}
创建类实例:
val person= Person() // Kotlin 中没有 new 关键字
//属性调用
person.name
Koltin 中的类可以有一个 主构造器,以及一个或多个次构造器,主构造器是类头部的一部分,位于类名称之后:
/*如果主构造器没有任何注解,也没有任何可见度修饰符,
那么constructor关键字可以省略。*/
class Person constructor(firstName: String) {//主构造器
}
//等价于
class Person(firstName: String) {}
/*没有主函数, 也可以如:自定义线性布局 ,
继承使用 : 接口和类都是 : 类后面要添加(), 接口不用*/
class MyLinearLayout : LinearLayout {
constructor(context: Context) : super(context) {//次构造器
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {//次构造器
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) :
super(context, attrs, defStyleAttr) {//次构造器
}
}
//等价于 有主构造函数, 可以不写次构造函数,
@JvmOverloads 关键字告诉虚拟器生成java代码, 会生成java的三个构造函数
//自定义线性布局
class MyLinearLayout @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr){}
getter 和 setter
//属性声明的完整语法:
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
var initialized = 1 // 类型为 Int, 默认实现了 getter 和 setter 可读可写
val inferredType = 1 // 类型为 Int 类型,默认实现 getter 只读属性
实例:
class Person {
var lastName: String = "zhang"
get() = field.toUpperCase() // 将变量赋值后转换为大写
set
var no: Int = 100
get() = field // 后端变量
set(value) {
if (value < 10) { // 如果传入的值小于 10 返回该值
field = value
} else {
field = -1 // 如果传入的值大于等于 10 返回 -1
}
}
var heiht: Float = 145.4f
private set
}
// 测试
fun main(args: Array<String>) {
var person: Person = Person()
person.lastName = "wang"
println("lastName:${person.lastName}")
person.no = 9
println("no:${person.no}")
person.no = 20
println("no:${person.no}")
}
非空属性必须在定义的时候初始化,kotlin提供了一种可以延迟初始化的方案,使用 lateinit 关键字描述属性:
class MyLinearLayout @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
private lateinit var mContext: Context//成员属性 不可为空
private lateinit var mText: String//成员属性 不可为空
//也可以这样声明 private var mText : String? = null 可空属性
fun setText(text: String) {
this.mText = text
}
init {//构造函数初始化
this.mContext = context
}
fun test(){
//声明时, 带? 使用时, 也要带? 和Java if(mText == null){} 等价
//使用lateinit(延迟初始化, 使用前, 必须初始化, 否则报异常)声明的变量使用时, 不用加? 但是会报空指针异常
mText?.plus("你好")
}
}
抽象类, 抽象是面向对象编程的特征之一,类本身,或类中的部分成员,都可以声明为abstract的。
//抽象成员在类中不存在具体的实现。
注意:抽象类和接口, 默认是open修饰的, 普通类默认final类,
不能被继承。 所有类, 不加public默认都是public权限
open class Base {
open fun f() {
}
}
abstract class Derived : Base() {
override abstract fun f()
}
嵌套类
class Outer { // 外部类
private val bar: Int = 1
class Nested { // 嵌套类
fun foo() = 2
}
}
fun main(args: Array<String>) {
val demo = Outer.Nested().foo() // 调用格式:外部类.嵌套类.嵌套类方法/属性
println(demo) // == 2
}
内部类
内部类使用 inner 关键字来表示。
内部类会带有一个对外部类的对象的引用,所以内部类可以访问外部类成员属性和成员函数。
class Outer {
private val bar: Int = 1
var v = "成员属性"
/**嵌套内部类**/
inner class Inner {
fun foo() = bar // 访问外部类成员
fun innerTest() {
var o = this@Outer //获取外部类的成员变量
println("内部类可以引用外部类的成员,例如:" + o.v)
}
}
}
fun main(args: Array<String>) {
val demo = Outer().Inner().foo()
println(demo) // 1
val demo2 = Outer().Inner().innerTest()
println(demo2) // 内部类可以引用外部类的成员,例如:成员属性
}
匿名内部类
class Test {
var v = "成员属性"
fun setInterFace(test: TestInterFace) {
test.test()
}
}
定义接口
interface TestInterFace {
fun test()
}
fun main(args: Array<String>) {
var test = Test()
/**
* 采用对象表达式来创建接口对象,即匿名内部类的实例。
*/
test.setInterFace(object : TestInterFace {
override fun test() {
println("对象表达式创建匿名内部类的实例")
}
})
}
click点击事件
mTextView?.setOnClickListener {//大括号内使用 it 代指调用者
//里面处理点击事件
}
修饰符
类的修饰符包括 classModifier 和_accessModifier_:
// classModifier: 类属性修饰符,标示类本身特性。
kotlin java
abstract // 抽象类 abstract
final // 类不可继承,默认属性 final
enum // 枚举类 enum
open // 类可继承,类默认是final的 没被final修饰的类
annotation // 注解类 annotation
accessModifier: 访问权限修饰符
kotlin java
private // 仅在同一个文件中可见 private
protected // 同一个文件中或子类可见 protected
public // 所有调用的地方都可见 public
internal // 同一个模块中可见 没有修饰符,
继承 Any所有类的超类, 类似于java中的Object
Kotlin 中所有类都继承该 Any 类,它是所有类的超类,对于没有超类型声明的类是默认超类:
class Example // 从 Any 隐式继承
Any 默认提供了三个函数:
equals()
hashCode()
toString()
如果一个类要被继承,可以使用 open 关键字进行修饰。
open class Base(p: Int) // 定义基类
class Derived(p: Int) : Base(p)
如果子类有主构造函数, 则基类必须在主构造函数中立即初始化。
open class Person(var name : String, var age : Int){// 基类
}
class Student(name : String, age : Int, var no : String, var score : Int) : Person(name, age) {
}
// 测试
fun main(args: Array<String>) {
val s = Student("Runoob", 18, "S12346", 89)
println("学生名: ${s.name}")
println("年龄: ${s.age}")
println("学生号: ${s.no}")
println("成绩: ${s.score}")
}
子类没有主构造函数
如果子类没有主构造函数,则必须在每一个二级构造函数中用 super 关键字初始化基类,或者在代理另一个构造函数。初始化基类时,可以调用基类的不同构造方法。
class Student : Person {
constructor(ctx: Context) : super(ctx) {
}
constructor(ctx: Context, attrs: AttributeSet) : super(ctx,attrs) {
}
}
重写: 在基类中,使用fun声明函数时,此函数默认为final修饰,不能被子类重写。如果允许子类重写该函数,那么就要手动添加 open 修饰它(抽象函数除外, 默认是open的), 子类重写方法使用 override 关键词:
/**用户基类**/
open class Person{
open fun study(){ // 允许子类重写
println("我毕业了")
}
}
/**子类继承 Person 类**/
class Student : Person() {
override fun study(){ // 重写方法
println("我在读大学")
}
}
fun main(args: Array<String>) {
val s = Student()
s.study();
}
属性重写 :
属性重写使用 override 关键字,属性必须具有兼容类型,每一个声明的属性都可以通过初始化程序或者getter方法被重写:
open class Foo {
open val x: Int get { …… }
}
class Bar1 : Foo() {
override val x: Int = ……
}
你可以用一个var属性重写一个val属性,但是反过来不行。因为val属性本身定义了getter方法,重写为var属性会在衍生类中额外声明一个setter方法
你可以在主构造函数中使用 override 关键字作为属性声明的一部分:
interface Foo {
val count: Int
}
class Bar1(override val count: Int) : Foo
class Bar2 : Foo {
override var count: Int = 0
}
接口
Kotlin 接口与 Java 8 类似,使用 interface 关键字定义接口,允许方法有默认实现
interface Demo{
fun add(a:Int, b:Int):Int // 未实现
fun minus(a: Int, b: Int): Int { //已实现
return a - b
}
}
一个类或者对象可以实现一个或多个接口
class SubDemo: Demo{
override fun add(a:Int, b:Int) : Int {
// 方法体
}
}
接口中的属性只能是抽象的,不允许初始化值,接口不会保存属性值,实现接口时,必须重写属性
interface Demo {
var name:String
}
class SubDemo : Demo{
override var name:String = "wwf"//重写属性
}
函数重写: 实现多个接口时,可能会遇到同一方法继承多个实现的问题。例如:
interface Demo1{
fun foo() { print("A") } // 已实现
fun bar() // 未实现,没有方法体,是抽象的
}
interface Demo2 {
fun foo() { print("B") } // 已实现
fun bar() { print("bar") } // 已实现
}
class Demo3 : Demo1 {
override fun bar() { print("bar") } // 重写
}
class Demo4 : Demo1, Demo2 {
override fun foo() {
super<Demo1>.foo()
super<Demo2>.foo()
}
override fun bar() {
super<Demo2>.bar()
}
}
fun main(args: Array<String>) {
val d = Demo4()
d.foo()
d.bar()
}
网友评论