Kotlin类和对象(三)——接口与访问修饰符

接口

Kotlin的接口和Java 8的接口很相似。它们可以包含抽象方法也可以包含方法的实现。与抽象类不同的地方在于,接口不可以存储状态。它们可以拥有属性,但是必须是抽象的或者提供访问器的实现。

使用关键词interface定义接口:

interface MyInterface {
    fun bar()
    fun foo() {
        // 可选的方法体
    }
}

实现接口

一个类或对象,可以实现一个或多个接口

class Child : MyInterface {
    override fun bar() {
        // body
    }
}

接口中的属性

你可以在接口中声明属性,接口中声明的属性可以使抽象的也可以提供访问器的实现。但是声明在接口中的属性,不可以有幕后字段,因此定义在接口中的访问器不能引用它们。

interface MyInterface {
    val prop: Int // 抽象属性
    val propertyWithImplementation: String
        get() = "foo"
    fun foo() {
        print(prop)
    }
} 
class Child : MyInterface {
    verride val prop: Int = 29
}

解决重写冲突

当我们在超级类型列表中声明多个类型时,会发现我们继承了不止一个相同方法的实现。如:

interface A {
    fun foo() { print("A") }
    fun bar()
} 
interface B {
    fun foo() { print("B") }
    fun bar() { print("bar") }
}
class C : A {
    override fun bar() { print("bar") }
} 
class D : A, B {
    override fun foo() {
        super<A>.foo()
        super<B>.foo()
    } 
    override fun bar() {
        super<B>.bar()
    }
}

接口A和接口B都申明了函数foo()和bar()。它们都实现了foo(),只有B实现了bar(),(A中的bar()没有用abstract标记,因为在接口中,如果函数没有函数体,那么该函数默认是抽象函数)。现在,如果我们从A类生成一个具体的C类,我们显然需要重写bar()和提供一个实现。

然而,如果我们从A和B类生成一个具体的D类,我们需要实现从多个接口中继承过来的所有方法,而且详细说明D需要怎样完全的实现它们。这个规则用于我们继承的单个实现(bar())和多个实现(foo())方法。

访问修饰符

类、对象、接口、构造函数、函数、属性和它的setter可以有访问修饰符(getter通常和属性有相同的访问属性)。Kotlin中有4个访问修饰符:private、protected、internal和public。如果没有使用显示的修饰符,将会使用默认的访问属性public。

函数、属性和类、对象和接口都可以定义在顶层(top-level),即,直接在包内:

// 文件名: example.kt 
package foo

fun baz() {} //顶层的函数
class Bar {} //顶层的类
  • 如果你没有具体说明任何修饰符,就默认使用public,这样你声明的包,就可以在任何地方被访问。
  • 如果你声明为private,那就只能在包含声明的文件内部可以访问。
  • 如果你声明为internal,它就可以在同一个模块的任何地方可以访问。
  • protected在顶层声明中不可以使用。

如:

// 文件名: example.kt 
package foo

private fun foo() {} // foo只在example.kt内可以访问
public var bar: Int = 5 // bar可以在任何地方范文。
    private set // setter 只在 example.kt内可以访问

internal val baz = 6// 在相同的模块中可以访问。

类和接口

当在类中声明成员时:

  • private 只能在类内部可以访问(包括它所有的成员)。
  • protected 不仅可以在类内部访问,还可以在子类中访问。
  • internal 在本模块中可以访问到声明类的终端就可以访问到声明的internal成员。
  • public 所有可以访问到声明类的终端就可以访问到声明的public成员。

例子:

open class Outer {
    private val a = 1 
    protected open val b = 2 
    internal val c = 3 
    val d = 4 // 默认是public

    protected class Nested {
        public val e: Int = 5 
    }
}

class Subclass : Outer() {//集成Outer类
    // a 不可以访问
    // b, c 可以访问 
    // Nested 和 e 可以访问

    override val b = 5 // 'b' 是protected可以被重写
}

class Unrelated(o: Outer) {//引用Outer类
    // o.a, o.b 不可以访问
    // o.c 和 o.d 可以访问 (相同模块) 
    // Outer.Nested 不可以访问, 而且 Nested::e 也不可以访问
}

构造函数

使用下面的句法(你需要显示使用关键词constructor)来具体说明类的主构造函数访问权限。

class C private constructor(a: Int) { ... }

这里的构造函数是private。所有的构造函数默认都是public,只要类可以被访问,它的构造函数也就可以被访问。(即,一个internal 类的构造函数只能在相同的模块中访问)。

局部声明

局部声明的变量、函数和类都不可以有访问修饰符。

模块

使用访问修饰符internal表示成员只能在相同的模块中访问。更明确地说,模块就是一系列的Kotlin文件编译在一起。

  • 一个IntelliJ IDEA模块
  • 一个Maven项目
  • 一个Gradle源码集合
  • Ant任务执行一次编译的一组文件

猜你喜欢

转载自blog.csdn.net/flueky/article/details/78311260
今日推荐