Kotlin专题「十一」:可见性修饰符(private、protected、internal、public)

前言:不要假装很努力,因为结果不会陪你演戏。

一、概述

  类,对象,接口,构造函数,函数,属性及其setter可以具有可见性修饰符(getter始终具有与属性相同的可见性)。在 Kotlin 中有四个可见性修饰符:private,protected,internal和public。默认可见性是public(在没有显式修饰符时)。

下面将会给大家讲解修饰符如何在应用声明作用域的不同类型。

这里先来介绍一下类的几种修饰符,它包含 classModifier 和 accessModifier

1.1 classModifier

  • open:     表示类可继承,类默认是final的;
  • final:     表示类不可继承,默认属性;
  • abstract:   表示抽象类;
  • enum:    表示枚举类;
  • annotation: 表示注解类;

1.2 accessModifier_

  • public:    表示公有,范围最大,所有调用的地方可见,具有最大的访问权限,可以被其他所有类访问,如果没有声明修饰符则系统会默认使用这个修饰符;
  • private:   表示私有,范围最小,仅在同一文件可见,只能被自己访问和修改;
  • protected:  表示私有+子类,同一个文件中或者子类可见,自己和子类及同一包中的类可以访问,不能用于顶层声明;
  • internal:   表示模块,同一个模块中可见。

二、使用

2.1 顶层声明

函数,属性和类,对象和接口可以在顶层top-level声明,即直接在包中声明:

//文件名:ModifierActivity.kt
package com.suming.kotlindemo.blog
fun send() { //默认public修饰
    //TODO
}

class ModifierActivity { //默认public修饰
}

如下图:

在这里插入图片描述

  • 如果没有指定任何可见修饰符,默认为 public,所以这些声明将随处可见;
  • 如果将声明标记为私有 private ,那么它将只在包含该声明的文件中可见;
  • 如果将声明标记为内部 internal ,它在同一个模块中随处可见;
  • protected 对顶级top-level声明不可用。

注意:要使用来自另一个包的可见顶级 top-level 声明,您仍然应该导入它。

举个例子:

//文件名:ModifierActivity.kt
package com.suming.kotlindemo.blog

private fun share() {//只在 ModifierActivity.kt 文件中可见
    //TODO
}

public var type: Int = 5 //public修饰,公共的,属性在哪都可见
    private set   //setter方法私有,仅在 ModifierActivity.kt 文件中可见

internal val name: String = "Kotlin" //在同一个模块内可见

//protected var sign = 0 //报错,protected不能用于顶级声明中

class ModifierActivity {
}

2.2 类

对于在类中声明的成员:

  • public:   表示任何看到已声明类的客户端都会看到它的公共成员;
  • private:   表示只在类内部可见(包括其所有成员);
  • protected:  表示只在当前类和子类中可见;
  • internal:   表示这个模块中任何看到声明类的客户端都看到了它的internal内部成员。

注意:在 Kotlin 中,外部类不会看到其内部类的私有成员。

如果你重写了一个 protected 修饰的成员而没有显式指定它的可见性,那么重写的成员也将具有protected的可见性。举个例子:

    //基类
    open class Outer {
        private val numA = 0
        protected open val numB = 1
        internal val numC = 2
        public val numD = 3

        //内部类
        protected class Inner {
            public val numE = 4
            private val numF = 5 //不可以被Outer访问
        }
    }

    //子类
    class Student : Outer() {
        //numA 不可见
        //numB、numC、numD 可见
        //Inner 和 numE 可见

        override val numB: Int = 10 // numB 是 protected 修饰的,同类和子类可见

        //使用如下:
        fun foo() {
            //numA //报错,不可见
            numB //可见
            numC //可见
            numD //可见
            Inner() //可见
            Inner().numE //可见
        }
    }

    class People(val outer: Outer) {
        //outer.numA, outer.numB 不可见
        //outer.numC, outer.numD 可见,属于同一个Module
        //Outer.Inner不可见,Inner::numE也不可见

        //使用如下:
        fun foo() {
            //outer.numA //报错,不可见
            //outer.numB //报错,不可见

            outer.numC //可见
            outer.numD //可见

            //Outer.Inner //报错,不可见
            //Inner::numE //报错,不可见
        }
    }

(2)构造函数

要指定类的主构造函数的可见性,使用以下语法(注意有可见性修饰符时, constructor 关键字不能隐藏):

    class Dragon private constructor(name: String) { //私有构造函数
        //辅助构造函数
        constructor(name: String, type: Int) : this(name) {
            //private val numA = 0 //报错,本地变量不能有可见性修饰符
            //protected val numB = 1 //报错
            //internal val numC = 2 //报错
            //public val numD = 3 //报错

            val numE = 4 //正确
        }
    }

这里的构造函数是私有的。默认情况下,所有的构造函数是 public 的,这意味着它们在类可见的任何地方都是可见的(例如,一个内部类的构造函数只在同一个模块中可见)。辅助构造函数{}中的属性和本地变量一样,不能有可见性修饰符。

(3)局部声明

注意:本地(局部)变量,函数和类不能有可见修饰符。

    class Rabbit {
        fun foo() {
            //public var textView = TextView() //报错,本地变量不能有可见性修饰符
            //private var textView = TextView() //报错
            //protected var textView = TextView() //报错
            //internal var textView = TextView() //报错

            //public fun invite() {} //报错,本地函数不能有可见性修饰符
            //private fun invite() {} //报错
            //protected fun invite() {} //报错
            //internal fun invite() {} //报错

            //public class Goose {} //报错,局部类不能有可见性修饰符
            //private class Goose {} //报错
            //protected class Goose {} //报错
            //internal class Goose {} //报错
        }
    }

可以看到,本地(局部)变量,函数和类不能有 publicprivateprotectedinternal可见修饰符。

2.3 接口

接口中的属性只能用 public 修饰,函数只能用 publicprivate 修饰,但是 private 修饰的函数不能被重写。要使用接口中的属性和方法则需要在实现中重写(可以参考我上一篇文章)。

    interface baseInterface {
        //接口中的属性默认是抽象的,private,protected,internal都不能与抽象 abstract 共用
        //private val numA: Int //报错
        //protected val numB: Int //报错
        //internal val numC: Int //报错
        public val numD: Int

        public fun share() {//能被重写
            numD
        }

        //private 可以修饰方法,并且可以使用接口中的属性,但是不能被子类重写
        private fun share2() {
            numD
        }

        //protected fun share3() //报错,protected不能修饰接口中的函数

        //internal fun share4() //报错,protected不能修饰接口中的函数
    }

    //实现类,要使用接口的属性则需要重写
    class Chicken : baseInterface {
        override val numD: Int = 0
        override fun share() {
            super.share()
        }
    }

对于在接口声明,因为接口中的属性默认是抽象的,即 abstract 修饰的,然而 privateprotectedinternal都不能与 abstract 修饰符共用,所以属性只能用 public修饰。

接口中的函数默认是 public 修饰的,private修饰的函数则不能被子类重写,protectedinternal都不能修饰接口中的函数。

2.4 模块

internal 修饰符表示该成员在同一个模块中可见。更具体的说,模块是一组共同编译的 Kotlin 文件:

  • 一个IntelliJ IDEA模块;
  • 一个Maven项目;
  • Gradle源集(test 源集可以访问 main 的内部声明除外);
  • 使用< kotlinc > Ant任务的一次调用编译的一组文件。

总的来说,可见性修饰符 Kotlin 与 Java 还是有不同之处:

  • 1.Kotlin 的四种修饰符:public、private、protected和internal;Java 的四种修饰符:public、privavte、protected和default(即不使用任何修饰符);
  • 2.Kotlin 中默认的修饰符为public,Java 中默认的修饰符为default。

源码地址:https://github.com/FollowExcellence/KotlinDemo-master

点关注,不迷路


好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才

我是suming,感谢各位的支持和认可,您的点赞、评论、收藏【一键三连】就是我创作的最大动力,我们下篇文章见!

如果本篇博客有任何错误,请批评指教,不胜感激 !

要想成为一个优秀的安卓开发者,这里有必须要掌握的知识架构,一步一步朝着自己的梦想前进!Keep Moving!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值