【问题标题】:What difference does it make to have Companion.foo in a companion object?Companion.foo 在伴生对象中有什么区别?
【发布时间】:2019-10-15 04:49:53
【问题描述】:

在 Kotlin 中,如果我在伴生对象中有一个以 Companion. 为前缀的函数 (Companion.foo),与伴生对象内的 foo 相比会有什么不同?

我注意到在下面的代码中,Companion.foo 将使它对外部范围不可见,但对同一伴随对象内的函数仍然可见。

您可以在以下位置找到代码 sn-p:https://pl.kotl.in/t6FvM6ni6

fun main() {
    A.foo() // compiler complains "unresolved reference"
    A.bar()
    B.foo()
}

class A {
    companion object {
        fun Companion.foo() {
            println("hello in A")
        }

        fun bar() {
            foo()
        }
    }
}

class B {
    companion object {
        fun foo() {
            println("hello in B")
        }
    }
}

还有其他区别吗?除了可见性之外,A.Companion.fooA.foo 是否相同?这是一种将方法封装在伴生对象中的方法吗?


更新 1

在我的实际项目中,我从伴随对象中的另一个inline 函数调用inline 函数,这就是不能使用访问修饰符的原因。但如果可能的话,我仍然想隐藏foo

class C {
    companion object {
        inline fun <reified T> Companion.foo() {
            println("hello in A")
        }

        inline fun bar() {
            foo<String>()
        }
    }
}

【问题讨论】:

    标签: kotlin kotlin-companion


    【解决方案1】:

    在您的示例中,定义Companion.foo()extension as a member。在这种情况下,您将扩展名定义为与扩展名类型相同的A.Companion。这没什么用。

    下一个示例将扩展的概念显示为具有两个不同类的成员。该示例没有同伴,因为它对概念没有任何影响。

    class A 
    
    class B {
        fun A.foo() {
            println("Extension for A, only visible in B")
            println("Function has two 'this' references: ${this} and ${this@B}")
        }
    
        fun bar() {
            val a = A()
            a.foo() // this function call is only possible in the context of `B`
        }
    }
    
    fun main() {
        val a = A()
        a.foo() // compile error
    }
    

    话虽如此,您示例中的两个foo() 函数在内部具有不同的签名。普通函数foo() 是一个不带参数的伴生对象上的简单方法。扩展函数Companion.foo() 是伴随对象上的一个方法,但为第二个this 引用提供了一个额外参数。

    要将方法封装在同伴中,只需将private 修饰符放在函数之前。

    如果您需要内联函数,请使用 internal@PublishedApi 对公共 API 隐藏该函数。

    class C {
        companion object {
            @PublishedApi
            internal inline fun <reified T> foo() {
                println("hello in A")
            }
    
            inline fun bar() {
                foo<String>()
            }
        }
    }
    

    【讨论】:

    • 感谢您的解释。我使用的是inline,所以private 不是一个选项。请参阅更新的问题描述。 Companion.foo 在这种情况下会有所帮助吗?
    猜你喜欢
    • 1970-01-01
    • 2018-02-01
    • 2020-07-26
    • 1970-01-01
    • 2021-02-12
    • 1970-01-01
    • 2010-10-11
    • 2011-09-23
    相关资源
    最近更新 更多