Kotlin学习笔记(五)面向对象编程

面向对象的本质:可以提升抽象的级别,以构建更大,更复杂的系统。简单点说就是,更好的应对需求不断变化的情况。武器就是:抽象!

这部分只讲和Java不同的一些点。

1. 构造函数

一个类可以有一个主构造函数,同时可以拥有多个次构造函数。这是乱的不得了。

  • 主构造函数
  1. 竟然跑到类头去了,直接放在类名的后面。
  2. 参数必须声明类型。
  3. 默认是public。
  4. 如果没有(public/private/protected)修饰,也没有任何注解。 Contructor也可以不写。
  5. 参数可是val,也可以是var。
  6. 可以有初始化值。
  7. 如果继承了一个类,那个类的构造初始化,也可以在类头处理。
class Student Constructor(var name:String, var age:Int){ //默认是public
}

class Student public Constructor(var name:String, var age:Int){
}

class Student private Constructor(var name:String, var age:Int){
}

class Student @AutoWire Constructor(var name:String, var age:Int){
}

class Student(var name:String, var age:Int){ //如果没有(public/private/protected)修饰,也没有任何注解。 Contructor也可以不写。
}

class Student Constructor(var name:String, var age:Int = 20){ //可以有初始化值。
}

class Student public Constructor(var name:String, var age:Int):Person(name){ //如果继承了一个类,那个类的构造初始化,也可以在类头处理。
}
  • init
  1. 由于主构造函数没有函数体。所以初始化放在了init模块中。相当于函数体了。
    class Student (var age: Int, var name: String ){   
        private var mAge: Int
        private var mName: String
    
        init {
            mAge = age
            mName = name
        }
    }
    
  2. 除了用init初始化,还可以直接在属性上初始化。
    class Student (var age: Int, var name: String ){   
        private var mAge: Int = age
        private var mName: String = name
    }
  • 次构造函数

在类体中,也可以声明前缀有Constructor的构造函数,次构造函数不能有声明val或var。

class Student {
    Constructor(name:String, age:Int){
    }
}

如果类既有主构造函数, 又有次构造函数。并且主构造函数初始化了父类的构造函数, 就是用this表示。this可以指代同类的其他构造函数, 这个和Java一样。

class Student(override var name:String, var age:Int):Person(name) {
    constructor(name:String, age:Int, weight:Int):this(name, age){ //这个this是主构造函数
    }

    constructor(name:String) :this(name,20,60) { //这个this是上面那个构造函数

    }
}

open class Person(open var name: String) {

}
  • 私有构造函数

只要如下这么写就可以了,加个private.

class Student private (var name:String, var age:Int){ //主构造函数私有

    private constructor(name:String) :this(name,20) {次构造函数私有

    }
}
  • 默认构造函数

和Java一样,默认也有一个无参构造函数。

  • 实例化类

实例化类是不需要new这个关键词的。很不习惯。

2. 类的属性

  • Kotlin的类属性都需要手动初始化, 不像java都给你初始化好了,比如基本类型都是初始化0, 对象都是初始化为null。
  • Kotlin的setter/getter,和C#很像,就是有点不伦不类。由于C#和Java一样,属性都是初始化好的,而Kotlin由于需要初始化属性,所以不能像C#一样用大括号括起来。另外,无法制定只重写abstract的getter或者setter。

    1. 当public时,默认就是getter/setter方法。

    
    class Student {
         var name: String = ""
         var age: Int = 1
    }
    
    
    var student:Student= Student("",1)
        student.age =1 //默认自带getter/setter
        student.name =""

    2. 下面是自动生成且隐藏的方法。

     set(vaule){
            field = value 
        }
        get() = field

      3. 当你需要修改getter/setter时,可以这样写:

class Student {
    var age: Int = 1
        get() = field
        set(value) {
             if (value < 18)
                 field =  18
            else if (value >= 18 && value <= 30)
                 field = value
            else
                 field = value - 3
        }
}

    4. 当属性有val修饰时,常量为只读属性,  所以只有getter方法。

  • 抽象类与抽象方法

  1. 这一块基本和Java一样。 唯一不一样的地方是,在抽象类中的非抽象方法,默认是final的,不能被重写,如果想被子类重写,必须用“open”修饰。 这样设计,不知道有什么好处。
  2. 在子类被重写的方法要用override修饰。
  • 抽象属性

由于在Kotlin中,属性是自带getter/setter的,所以就存在抽象属性的概念了。抽象属性在抽象类中不能被初始化,而在子类中必须初始化,否则子类也是抽象类。

abstract class Student {
    abstract var name: String
    abstract var age: Int
}

如果子类中有主构造函数,可以在主构造函数里初始化,如下:

class Person(override var name: String, override var age: Int) :Student() {

}

如果没有主构造函数,就要对抽象属性手动初始化。

class Person : Student() {
    override var name: String = ""
    override var age: Int =1
}
  • 实现接口

这一块也差不多和java一样。

  1. 对于父类的包访问权限成员变量,如果子类和父类都在同一个包,则子类可以继承,否则不许。
  2. 当子类和父类的方法一样时,用super来访问父类的方法。
  3. 当有多个一样的父类方法时,用super<具体父类>.来访问方法。

继承

所有的类都默认继承Any,有点像Java的Object, 但是又有不同,因为只有equals(), hashcode(), toString()三个方法。不像JAVA Object还有clone/wait/notify/finanlize等。

枚举类

Abstruct class Enum():Comparable{

public final val name:String

public final val ordinal:Int

}

name和ordinal是唯二的两个属性。分别表示枚举对象的值和下标位置。和Java类似。 比较好的是和C#一样,枚举值为自增加一。

使用enumValues()方法可以遍历打印枚举。

enum class RGB{

RED(200), GREEN(100),BLUE(50)}

}

val rgbs = enumValues.joinToString{"${it.rgb}:${it.name}:${it.ordinal}"}

输出rgbs:200: RED:0, 100: GREEN:1,50: BLUE:2

枚举常量也可以声明自己的匿名类。这种用法以前倒是没见过。

enum class ActivityLifeState{

onCreate{

override fun signal()=onStart()

}

abstract fun signal():ActivityLifeState

}

var oncreate= ActivityLifeState.onCreate

oncreate.signal()

object关键词

很好的场景就是一些Utils的工具类了。

Kotlin中没有静态属性和方法,但是可以用object关键词。在类名前加object关键词,就相当于在类型前加了static, 变成了静态类,用法也一样,用类名调用方法和成员属性。而且成员属性默认都是final static的。而且不能实例化object关键词修饰的类。

把object修饰的类,反编译到Java代码后就容易理解了。

public final class User{

private final static String name = "alan";

private static final User INSTANCE;

private User(){

INSTANCE = (User)this

name ="alan"

}

static {

new User();

}

}

在类中嵌套使用object关键词, 这个用法和java静态类一样。

匿名object

有时候仅仅是一个简单的对象,可以用匿名object。但是只能在本地和私有作用域里声明使用。

class AnonymousObjectType{

private fun privateFoo()=object{

val x:String="x"

}

fun publicFoo()=object{

val x:String="x" //无法访问到

}

fun test(){

val x1 = privateFoo().x //正确,WORK

//val x2 = publicFoo().x//Error

}

}

匿名内部类

内部类。不再像java那样默认带有外部对象的引用了。

        setOnClickListener(object:OnFilteredClickListener(){
            override fun onFilteredClick(v: View?) {
                TODO("Not yet implemented")
            }
        })

未完待续

你可能感兴趣的:(kotlin,java,android)