转向Kotlin——类和接口

Posted Android机动车

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转向Kotlin——类和接口相关的知识,希望对你有一定的参考价值。

类的声明

和Java没有什么两样,Kotlin中,类的声明也使用class关键字,如果只是声明一个空类,Kotlin和Java没有任何区别,不过定义类的其他成员,区别就很大了。

class MyClass{
}

类的构造器

构造器也叫构造方法,是类创建的必要元素。

1、主构造器

面向对象语言在定义类的时候,都需要至少制定一个构造方法,如果不指定构造器,编译器会默认生成一个不带任何参数的构造器,这是传统面向对象语言的做法。

Kotlin会有一些不一样的地方,在Kotlin中,类允许定义一个主构造器,和若干个第二构造器。主构造器是类头的一部分,紧跟在类名的后面,参数是可选的。如下代码定义了一个类,并指定了一个主构造器。

class Person constructor(name: String) {
}

如果主构造器没有任何注解,任何修饰,constructor可以省略:

class Person(name: String) {
}

上面的代码只是声明了主构造器,是在哪里实现构造器呢?如果是主构造器,需要在init代码块中进行初始化主构造器:

class Person(name: String) {
   val myName = name
   init {
       println(name)
   }
}

注意:主构造器中的参数不仅可以在init代码块中使用,还可以对类的属性进行初始化。

var和val也可以修饰主构造器参数,如果使用var,表示参数对于构造器来说是变量,在构造器内部可以对其进行操作和改变;如果使用val,表示该参数是常量,在构造器中不能修改它的值。但要注意的是,var修饰的参数,在主构造器中修改值后,并不会把修改后的值传到对象外面。

class Person(var name: String) {
   init {
       name="haha"
       println(name)
   }
}

2、第二构造器

Kotlin的类中,除了可以声明一个主构造器之外,还可以声明若干个第二构造器,第二构造器必须在类中声明,前面必须加constructor关键字。

class Person(var name: String) {
   init {
       name = "hello"+ name
       println(name)
   }
   constructor(age: Int) : this("js") {
       println(name + " " + age)
   }
   constructor(sex : Byte) :this(20){
       println(name +" "+ sex)
   }
}

明了主构造器,那么所有的第二构造器必须在声明的后面调用主构造器,或者通过另外一个第二构造器间接地调用主构造器。

当然,如果类中并没有声明主构造器,第二构造器后面可以不调用主构造器。

上面Person类中一共定义了三个构造器,就涉及到了构造器的重载,也就是一个类中拥有不同个参数和参数类型的构造器。

注意:主构造器中可以使用var和val修饰参数,但第二构造器中不能使用,也就意味着第二构造器中的参数都是只读的。

3、Kotlin的单例模式

我们只是大概了解以下Kotlin的单例模式如何书写,后面会详细介绍。

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

4、函数中的默认参数

有很多变成语言是支持默认参数的,也就是在调用函数的时候不指定参数值,就会使用默认的参数值。Java不支持,但Kotlin是支持的,先看个例子:

class Class(param: Int, param1: String = "js") {
}

在创建Class对象时,可以只传第一个参数,第二个参数可以不传,如Class(5),其第二个参数默认为"js"。

由于Kotlin支持默认参数,所以没有必要非要定义一个没有参数的构造器,可以直接定义一个所有参数都有默认值的构造器。

5、创建类实例

创建Kotlin实例在之前已经用到过了。对于大都数面向对象的语言来说,创建类实例的时候都会用到new关键字,但Kotlin中不再需要,直接调用构造器即可,如MyClass()。

类成员

1、属性的基本用法

Java开发者对JavaBean一定特别熟悉,其实JavaBean就是一个普通的Javak类,关键在于对属性的get和set方法。当然Java可以直接使用public的成员变量来解决这个问题,但对于属性来说,不仅仅能读写其值,还需要对其进行二次加工,所以get/set也是必须的。

Kotlin中的属性语法,只有var/val和属性名时必须的,其他都是可选的。也就是说,Kotlin属性最简单的形式就是在类中定义一个变量(var)或常量(val),要引用属性,就像引用变量一样。

class Class{
   var name:String="js"
   val int:Int=2
   fun pri(){
       println("name=${name} int=${int}")
   }
}

2、属性的get/set方法

因为Kotlin支持属性语法,所以并不需要对每个单独定义get和set方法。如果属性只是可读的(val),只需添加一个get方法,如果属性是读写的,添加get和set方法。g如果get/set方法只有一行代码,直接用=分隔即可,如果有多行代码,则z使用{}处理:

class Class {
   var name: String
       get()
= name
       set(value)
{
           name = value
       }
   val age: Int
       get()
= age
}

3、保存属性值的字段

Kotlin中可以使用filed标识符当作成员变量使用,也就是通过filed读写属性值:

class Class {
   var name: String = "js"
       get() = field
       set(value)
{
           field = value
       }
}

4、函数

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

说到构造器时,构造器支持默认参数值,实际上,函数也支持默认参数值。要注意的是,带默认值的参数必须是最后几个参数,也就是说,如果某个参数带有默认值,那么该参数后面的所有参数必须都有默认值:

class Class {
   fun func(url: String, host: String = "www.baidu.com") {
   }
}

但是如果带默认值的参数过多,在调的时候也会带来一些麻烦,如下:

class Class {
   fun func(url: String, host: String = "www.baidu.com", name: String = "haha") {
   }
}

当我想调用func方法,host参数使用默认值,而name参数自定义,就不得不在调用方法的时候将host参数显示地传"www.baidu.com"。为了解决这个问题,Kotlin允许使用命名参数传递参数值,所谓命名参数,就是在调用函数的时候指定形参名(host、name),这样就可以直接为指定的参数传值了,如:

Class().func("hh",name="hello")

如果传入函数的参数个数不固定,可以使用可变参数,可变参数用vararg关键字声明:

class Class {
   fun func(url: String, host: String = "www.baidu.com", name: String = "haha") {
   }
   fun func2(vararg names: String) {
       for (name in names) {
           println(name)
       }
   }
}

很多时候,函数体中只有一行代码,用传统的写法就比较麻烦了,这时可以直接在函数声明后加等号(=),后面直接跟代码,这种方式可以省略函数返回值类型:

class Class {
   var value: Int = 1
   fun func(url: String, host: String = "www.baidu.com", name: String = "haha") {
   }
   fun func2(vararg names: String) {
       for (name in names) {
           println(name)
       }
   }
   fun func3() = value
}

同时,在函数体内也可以定义函数,这种函数叫做本地函数,不再累赘。

5、嵌套类

所谓嵌套类,就是直接在n类内部再定义一个类。

class People {
   class Student {
   }
}
People.Student()

内部类还可以用inner声明,表示可以通过外部类的实例进行调用:

class People {
   inner class Student {
   }
}
People().Student()

修饰符

Kotlind的修饰符一共四个:private、protected、internal和public。

  • private:仅在类的内部可以调用;

  • protected:类似private,但在子类中也可以访问;

  • internal:模块中的任何类都可以调用;

  • public:任何类都可以访问。

如果不指定修饰符,默认全是public的,这些修饰符可以用在普通的类中,也可以用在构造器中。

类的继承

1、如何继承

与Java不同,Kotlin类的继承需要使用冒号(:),而Java使用extends。注意,冒号后面需要调用父类的构造器。

Kotlin和Java一样,都是单继承的,也就是说,一个Kotlin类只能有一个父类。要注意的是,Kotlin类默认是final的,也就是不允许继承的,需要显示地用open关键字声明,表示此类可以被继承。

open class School {
}
class MiddleSchool : School() {
}

2、重写方法

Kotlin中不仅类默认是不可以被继承的,连方法默认也是不可以重写的。因此,如果要在子类中重写方法啊,那么父类的对应方法必须用open修饰,而且要在子类重写的方法前面加override关键字:

open class School {
   open fun func() {
   }
}
class MiddleSchool : School() {
   override fun func() {
   }
}

如果一个方法已经被override修饰了,那么这个方法已经就被重写了,依然可以被它的子类所重写。

3、重写属性

属性的重写与方法类似,被重写的属性也必须用open修饰,子类属性必须用override修饰。不过要注意,val属性可以被重写为var属性,但反过来不可以:

open class School {
   open val name: String = "School"
   open fun func() {
   }
}
class MiddleSchool : School() {
   override var name: String = "MiddleSchool"
   override fun func() {
   }
}

接口

接口是另一个重要的面向对象元素,用于制定规范,强调对象是否具有某个功能。

Kotlin与Java类似,使用interface声明接口,一个类可以实现多个接口,实现的方法和类继承相同,而且,接口中的属性和方法都是open的。

interface MyInterface {
   fun func()
   fun func2(): String {
       return "js"
   }
}
class MyClass : MyInterface {
   override fun func() {
   }
}

上述代码中可以看出:实现接口与继承父类类似,使用冒号(:),但后面不是调用构造方法,而是是指跟接口名;Kotlin中的接口的方法,允许包含默认方法体,对于这样的额方法,子类实现接口时不一定必须实现该方法。

抽象类

抽象类和接口非常相似,抽象类不能被实例化,需要abstract关键字声明,抽象类实现接口后,接口中没有函数体的函数可以不重写,接口中的这些方法自动被继承到子类中,称为抽象方法:

abstract class MyAbsClass{
   abstract fun f()
}

抽象方法没必要用open声明,因为抽象类本身就是可以被继承的。

小结

Kotlin中的类e和接口与Java中的本质上没有什么两样,只不过Kotlin为了体现差异,加入了一些语法糖,如接口允许函数带函数体,支持属性,不支持静态方法等。我们需要慢慢去熟悉它。



以上是关于转向Kotlin——类和接口的主要内容,如果未能解决你的问题,请参考以下文章

kotlin类和接口

kotlin类和接口

kotlin类和接口

kotlin学习总结——类和对象继承接口和抽象类

Kotlin学习之旅解决错误:kotlin.NotImplementedError: An operation is not implemented: Not yet implemented(代码片段

Spring 代理类和 Kotlin 中的空指针异常