1

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

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

您可以在以下位置找到代码片段: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.foo和一样?A.foo这是一种将方法封装在伴生对象中的方法吗?


更新 1

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

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

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

1 回答 1

2

在您的示例中,定义Companion.foo()作为成员的扩展。在这种情况下,您以与扩展类型相同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>()
        }
    }
}
于 2019-10-15T05:38:39.063 回答