读书笔记第三章

186 阅读4分钟

构造器

kotlin允许定义一个柱构造器和若干个第二构造器,主构造器是类头的一部分,构造器的参数是可选的,下面的代码定义了一个Person类,并指定了一个主构造器。

class Person constructor (firstName:String)

如果主构造器没有任何的注释或修饰器,constructor关键字可以省略

class Person(firstName:String){ init{ println(firstName) } }

注意:如果是主构造器,需要在init构造块中进行初始化,在init块中,可以直接使用主构造器的参数。 java 代码:

classs Person{
    public Persion(String firstName){
        System.out.println(firstName)
    }
}

注意:柱构造器的参数不仅可以用在init块中,还可以初始化类属性

  • 第二构造器(可以声明若干个构造器,构造器前面必须加constructor)
class Person
{
    contructor(parent :Person){
        println(parent)
    }
}

注意:

  • 主构造器中参数可以使用var val,第二构造器不能使用var val,意思是第二构造器的参数是不可修改的,只能读
  • 第二构造器中必须调用主构造器
//java的Singleton
class  Singleton{
    private static Singleton mInstance = new Singleton();
    
    private Singleton(){
        
    }
    
    public Singleton getInstace(){
        return mInstance;
    }
}

//kotlin的单例模式

class Singleton private constructor(){
    public var value:Singleton? = null;
    private object mHolder {
        var INSTANCE = Singleton()
    }
    
    companion object Factory{
        fun getInstance:Singleton{
            return mHolder.INSTANCE
        }
    }
}


var obj1 = Singleton.getInstance()

java与kotlin实现的方式不同(差别很大),主要原因是kotlin不支持静态方法和变量,由于kotlin支持全局函数和变量,所以可以用这个替代静态方法和变量

kotlin中Objects可以解决没有static引起的麻烦

kotlin函数中的默认参数

kotlin可以在主构造中设置默认参数的,java是不可以的

class Customer (val customerName : String = "bill",var value : Float = 20.4F)
{

}

创建类的实例kotlin可以省略new关键字,

类成员

var修饰的是变量,val修饰的是常量

kotlin的属性

var/val propertyName:propertyType = propertyinitializer
getter
setter

只有var/val propertyName是必须的,其他的都是可选的

####属性的getter和setter

如果getter或settter中只有一行代码,可以用“=”分隔开即可,如果是多行需要用{}

class Customer
{
    val name :String
    //only read
    get() = "bill"
    
    //read and write
    var v:int = 2
    get() = v
    set(value){
        print("dkdkkddk")
        v = value
    }
}

####通过field保存属性值的字段

class Customer{
    val name : String 
        get() = "bill"
        
        
    var value :String
        get() = field
        set(value){
            print("dkdkdkd")
            field = value
        }
}

####函数

在kotlin中函数既可以在类的外部中定义,也可以在类的内部中定义,如果是前者则为全局函数,如果是后者则为类的成员函数,无论哪里定义,语法规则是一样的

  • 函数也是可以有默认值的,如果有默认值则必须写在参数的后面
class QACommunity{
    fun printQACommunity(url : String,schema:String = "https"){
        println("${schema}://${url}")
    }
}


// invoke like this


QACommunity().printQACommunity("www.baidu.com")

调用函数,只修改指定的默认值,可以如下调用

Person().process(30,"bill",salary = "100万/年")

可变参数的声明(vararg)

class Person (name:String){
    private var nName :String = name
    fun getName() :String
    {
        return mName
    }
}


class Persons 
{
    fun addPersons(vararg persons:Person):List<Person>{
        val result = ArrayList<Person>()
        for(person in persons){
            result.add(person)
            return result
        }
    }
}

  • 如果kotlin函数体中只有一行代码,可以直接在函数声明后加等于("="), 后面直接加代码,这种表达方式可以省略函数返回值类型。

修饰符(修饰符)

//"open" express Outer class can be extended
open class Outer{
    
    private val a= 1
    protected val b = 2
    internal val c = 3
    val d = 4 //default modifier is public
    protected class Nested 
    {
        public val e:Int = 5
    }
    
}

class Subclass :Outer (){
    //can not be access super class "a" val
    //b c d e can be accessed 
    override val b = 5
}

类的继承

  • kotlin 默认也只能单继承用的是冒号,java用的是extended
  • kotlin 默认的类是不允许继承的,需要用open关键字显示声明
重写方法
open class Parent 
{
    protected var mName:String = "bill"
    
    // only open added could be extended
    open fun getName() :String
    {
        return mName
    }
}

open class child :Parent{
   override fun getName():String{   //如果禁止子类重写本方法,在这行最前面加final
       return "[" + super.getName() + "]"
   }
}


重写属性

属性与方法类似,被重写的属性必须用open声明,子类中重写的属性必须用override声明,val属性可以被重写为var,返过来不可以

open class Parent {
    open val name:String = "bill"
    get(){
        println("”获取 Parent.name 属性值”")
        return field
    }
}

open class child :Parent(){
    override var name:String = "tom"
    get(){
        println (”获取 Child.name 属性值”)
        return field
    }
    set(value){
        
        field = value
println (”Child.name 被写入”)
    }
}





fun main(args:Array<String>){
    var child= Child()
}

接口

  • 接口中的属性和方法都是open的

//感觉有点像java的抽象类 interface MyInterface{ fun process() fun getName(){ // 可以不用重写此方法 return "bill" } }

小结

如果从作用上来说, Kotlin 中的类和接口与 Java 的类和接口 没什么本质上的差异,只不 过 Kotiin为了体现差异,加了一些语法糖,如接口允许函数带函数体,支持类属性,不支持静 态方法等。这些改进到底好不好,仍然需要时间去证明。不过既然 Kotlin 提供了这些功 能,我 们不妨去尝试一下,看看是否能给我们的开发工作提供便利 。