面向对象的本质:可以提升抽象的级别,以构建更大,更复杂的系统。简单点说就是,更好的应对需求不断变化的情况。武器就是:抽象!
这部分只讲和Java不同的一些点。
一个类可以有一个主构造函数,同时可以拥有多个次构造函数。这是乱的不得了。
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){ //如果继承了一个类,那个类的构造初始化,也可以在类头处理。
}
class Student (var age: Int, var name: String ){
private var mAge: Int
private var mName: String
init {
mAge = age
mName = name
}
}
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这个关键词的。很不习惯。
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方法。
抽象类与抽象方法
由于在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一样。
继承
所有的类都默认继承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
输出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")
}
})
未完待续