0
点赞
收藏
分享

微信扫一扫

Android - Kotlin 普通类,构造函数,抽象类,内部类等


一、类的声明

1、关键字

声明类的关键字为class

二、类的构造函数

  • 在Kotlin中,允许有一个主构造函数和多个二级构造函数(次构造函数)。其中主构造函数是类头的一部分。
  • 关键字或者构造函数名:constructor(参数)

主构造器

主构造器中不能包含任何代码,初始化代码可以放在初始化代码段中,初始化代码段使用 init关键字作为前缀。

class Person constructor(firstName: String) {
init {
println("FirstName is $firstName")
}
}

次构造函数

类也可以有二级构造函数,需要加前缀 constructor:

class Person { 
constructor(parent: Person) {
parent.children.add(this)
}
}

如果类有主构造函数,每个次构造函数都要,或直接或间接通过另一个次构造函数代理主构造函数。在同一个类中代理另一个构造函数使用 this 关键字:

class Person(val name: String) {
constructor (name: String, age:Int) : this(name) {
// 初始化...
}
}

主构造函数、次构造函数详解:

open class People {
}

Java 中类是可以默认继承的,但是 Kotlin 不一样。如果想要在 Kotlin 中的类被继承,那么需要使用关键字 open。

class Student : People() {
}

Java 中继承使用 extends,Kotlin 中继承使用 " : " 来处理。Java 中类继承不需要括号, Kotlin 中类继承需要括号。

主构造函数

  • 父类无参构造函数

//不带参数
class Student (): People() {
}

每个类有个默认不带参数的主构造函数。
主构造函数的特点-> 没有函数体,直接定义在类名后。

//带参数
class Student(sno: String, grade: Int) : People() {
}

Java 和 Kotlin 一样,子类的构造函数必须调用父类的构造函数。
上面代码中 Student 类初始化主构造函数时候会调用 People 类的无参主构造函数,即使没有参数也不能省略,所以这也是 Kotlin 中继承类有括号的原因。

  • 父类有参构造函数

class Student(sno: String, grade: Int, name: String, age: Int) : People(name, age) {
}

当父类主构造函数带参数时,由于子类必须实现父类主构造函数,所以可以在子类的主构造函数中加入父类构造函数需要的参数。

如果子类有主构造函数, 则基类必须在主构造函数中立即初始化。

次构造函数

class Student(sno: String, grade: Int, name: String, age: Int) : People(name, age) {
constructor(name: String, age: Int) : this("", 0, name, age) {
}
constructor() : this("", 0) {
}
}

1-> 次构造函数通过 constructor 关键字定义
2-> Kotlin 规定所有次构造函数必须调用主构造函数 

  • 特殊情况,子类和父类都没有构造函数

class Students : Persons {
constructor(name: String, age: Int) : super(name, age) {

}
}


open class Persons {
constructor(name: String, age: Int) {

}
}

子类没有主构造函数所以不用带括号,同理父类也是一样。

如果子类没有主构造函数,则必须在每一个二级构造函数中用 super 关键字初始化基类,或者在代理另一个构造函数。初始化基类时,可以调用基类的不同构造方法。

实例

/**用户基类**/
open class Person(name:String){
/**次级构造函数**/
constructor(name:String,age:Int):this(name){
//初始化
println("-------基类次级构造函数---------")
}
}

/**子类继承 Person 类**/
class Student:Person{

/**次级构造函数**/
constructor(name:String,age:Int,no:String,score:Int):super(name,age){
println("-------继承类次级构造函数---------")
println("学生名: ${name}")
println("年龄: ${age}")
println("学生号: ${no}")
println("成绩: ${score}")
}
}

fun main(args: Array<String>) {
var s = Student("Runoob", 18, "S12345", 89)
}

//输出结果:
//-------基类次级构造函数---------
//-------继承类次级构造函数---------
//学生名: Runoob
//年龄: 18
//学生号: S12345
//成绩: 89

抽象类

抽象是面向对象编程的特征之一,类本身,或类中的部分成员,都可以声明为abstract的。抽象成员在类中不存在具体的实现。
注意:无需对抽象类或抽象成员标注open注解。

open class Base {
open fun f() {}
}

abstract class Derived : Base() {
override abstract fun f()
}

嵌套类

嵌套类使用 Nested 关键字来表示。

class Outer {                  // 外部类
private val bar: Int = 1
class Nested { // 嵌套类
fun foo() = 2
}
}

fun main(args: Array<String>) {
val demo = Outer.Nested().foo() // 调用格式:外部类.嵌套类.嵌套类方法/属性
println(demo) // == 2
}

内部类

  • 内部类使用 inner 关键字来表示。
  • 内部类会带有一个对外部类的对象的引用,所以内部类可以访问外部类成员属性和成员函数。

class Outer {
private val bar: Int = 1
var v = "成员属性"
/**嵌套内部类**/
inner class Inner {
fun foo() = bar // 访问外部类成员
fun innerTest() {
var o = this@Outer //获取外部类的成员变量
println("内部类可以引用外部类的成员,例如:" + o.v)
}
}
}

fun main(args: Array<String>) {
val demo = Outer().Inner().foo()
println(demo) // 1
val demo2 = Outer().Inner().innerTest()
println(demo2) // 内部类可以引用外部类的成员,例如:成员属性
}

类的修饰符

类属性修饰符,标示类本身特性。

abstract    // 抽象类  
final // 类不可继承,默认属性
enum // 枚举类
open // 类可继承,类默认是final的
annotation // 注解类

 访问权限修饰符

private    // 仅在同一个文件中可见
protected // 同一个文件中或子类可见
public // 所有调用的地方都可见
internal // 同一个模块中可见

举报

相关推荐

0 条评论