美文网首页
About Kotlin-Kotlin中的类1

About Kotlin-Kotlin中的类1

作者: deep_sadness | 来源:发表于2017-08-18 13:54 被阅读23次

About Kotlin(1)

因为是从Java的角度来学习Kotlin,在Java中,类作为第一等公民。故学习Kotlin,也先从其的类开始。

Kotlin中的类

参考文章

  1. https://hltj.gitbooks.io/kotlin-reference-chinese/content/txt/object-declarations
  2. http://blog.csdn.net/zxc123e/article/details/73618709
  3. http://blog.csdn.net/zxc123e/article/details/73650039

普通的类 class

Kotlin中没有添加修饰符直接以class开头的都是final类。final类的意义在于JVM可能存在的优化(常量和方法内联)和防止继承的滥用。

《Effective Java》在第17条说,要么为继承而设计,并提供文档说明,要么就禁止继承。

构造方法

Kotlin中一个类有一个primary的构造方法和可以多个的secondary的构造方法。

//如果一个类,没有类体,甚至连花括号都可以省略
class Empty
//如果主构造方法没有注解/修饰符。则constructor可以直接省略
class Person constructor(firstName:String){}
//省略的写法
class Person(firstName:String){}
//注解
class Person @Inject constructor(firstName:String){}
//修饰符
class Person private constructor(firstName:String){}
//第二构造器
class Person(val name:String){
  //可以只用this,来指代第一个构造器
    constructor(name:String,parent:Person):this(name){
      //方法中,this同样可以用来指代对象
        parent.childeren.add(this)
    }
}
初始化
//如果使用默认构造方法的话,初始化代码不能现在方法内
class Customer(name:String){
  //使用init代码块来完成主构造函数的中的初始化
    init{
        logger.info("Custormer initialized with value ${name}")
    }
}
//另外,主构造函数传入的值,可以直接在类的变量中使用
class Customer(name:String){
  //属性变量可以直接使用构造函数中的变量
    val cumtomerKey = name.toUpperCase()
}
//通过这样,可以将主要构造方法中的参数直接变成类的属性.还可以直接写默认值
//在JVM上面会自动生成无参构造方法
class Customer(val firstName:String="",var lastName:String,var age:Int){
    
}

Kotlin中可以提供默认值的方式,解放了手写的代码量,及构造器模式Builder Pattern!

Effective Java的条目2讲述了如何有效地使用构造器模式(Builder Pattern)当Java构造函数有很多可选参数时,代码将变得冗长,可读性差且容易出错。构建这样的对象需要写很多代码。

对应的Open类

对应上面的类,kotlin中的open类就是能够被继承的了。必须在类声明的时候使用open关键字。Kotlin社区有人对这个 “默认的final” 设计很不满。Kotlin论坛对此进行了激烈的讨论。后来,在Kotlin 1.1 beta版中提供了一个编译器插件,可以让class默认是open。

//Kotlin中所有类的父类是Any,类似于Object,不过Any不输于java.lang.Object,其有三个方法
//这里的operator是操作符重载,在Kotlin中的符号中会说明
public open operator fun equals(other:Any?):Boolean
public open fun hashCode():Int
public open fun toString():String

覆盖方法

override的强制使用。

Java 1.5 中加入了注解(annotation),其中最重要的一个是重写(override),表示这个方法是对超类中该方法的重写。基于书中条目36,应该尽量使用这个可选注解以避免一些恶心的bug。比如当你以为你重写了超类的方法但其实并没有时,编译器会抛出一个错误。不过如果你记得加上了override注解的话就没事。

在Kotlin中,override不是可选的注解而是强制关键字。所以由此引发的bug就不会再有了,编译器会提前警告你。Kotlin把这些事清楚的展现出来。

open class Base{
    open fun v(){}
  fun nv(){}
}
class Derived():Base(){
  //override 关键词的使用
    override fun v(){}
}

//如果使用相同的两个方法。则可以用super类指代不同的父类的方法
interface B{
    fun v(){print("B")} //interface也能够写方法的实现
}
class DoubleImpl():Base(),B{
    override fun v(){
        //调用 Base.v()
      super<Base>.v()
      //调用B的方法的话
      super<B>.v()
    }
}

//这里还有个需要注意的是,属性的重写也需要用override
open class Foo{
    open val x:Int get{...}
}
class Bar1:Foo(){
    override val x:Int=...
}

数据类

所谓的数据类,就是Java的Pojo,除了字段外,基本不会写其他的方法。

//在Kotlin中,可以使用data关键字
data class User(val name:String,val age:Int)
自动生成的函数

编译器会自动的从主构造函数中根据所有声明的属性提取以下函数

  • equals()/hashCode()

  • toString

  • componentN() functions 对应属性。按照顺序排列

  • copy 函数。

    //关于深拷贝的例子。有时候只是需要修改部分的属性
    val java = User(name="Jack",age=1)
    val oderJack = java.copy(age=2)
    //对于上面User类。copy的实现就如下
    fun copy(name:String=this.name,age:Int=this.age)=User(name,age)
    
确保有意义

为了确保数据类是一致的并且有意义的。该类必须有至少一个参数,不能其他的类型。

如果生成的类需要无参构造函数,则所有的属性必须指定默认值

解构声明赋值

注意,这个解构声明是专属于data class的

data class Person(var name:String="lisi",var age= 12)
val person = Person("kobe",30)
//将对象解构
val (name,age)=person
//内部实现为
val name = person.component1()
val age = person.component2()

var (name,_)=Person()   //不需要使用变量时,可以用下划线替代

下面这个是一个更直接的例子

//因为有了ComponentN方法,才可以使用解构函数
class Pair<K,V>(val first:K,val second:V){
    operator fun component1():K{
        return first
    }
  
  operator fun component2():V{
      return second
  }
}
//vararg 是可变参数的意思
fun main(vararg args:String){
    val pair = Pair(first=1,second="One")
  val (num,name)=pair
  println("num=$num,name=$name")
}

相关文章

网友评论

      本文标题:About Kotlin-Kotlin中的类1

      本文链接:https://www.haomeiwen.com/subject/naharxtx.html