我想要有一个接口/抽象类B,它要求实现者A有一个公共构造函数,并且还实现了一组内部只有成员.以便其他模块可以构造A,但不能使用其上的内部方法.

一些内部成员表示与此模块中的其他类相同的功能性,因此我为它们创建了一个接口I,以允许在useI等函数中进行组合和使用.

另外,我不能把I作为一个抽象类,因为它被用在已经有super的类上,而多重继承在Kotlin中是不可能的.

我想出了这一点,但它不起作用,因为实现的接口的成员是公共的,我无法更改这一点.我可以将I设置为公共的,但这将意味着将许多内部类型和内容公开为公共的(实际上几乎所有模块),这不应该与其他模块有任何关系.

public abstract class B : I {

    internal abstract fun doStuff()
}

internal interface I {
    fun doOtherStuff()
}

public class A : B() {
    internal override fun doStuff() {
        // ...
    }

    internal override fun doOtherStuff() { // This is not possible in kotlin?
        // ...
    }
}

internal fun useI(i: I) = ...
useI(A())

对我来说,这样的事情似乎很奇怪,不可能像Kotlin 那样使用如此高级的语言,所以我错过了什么?我怎么发动汽车呢?

推荐答案

这是不可能的.根据Kotlin Language Specification,接口成员必须都是公共的.

  • 所有接口成员属性和函数都是隐式公共的;
    • try 在接口中声明非公共成员属性或函数是编译时错误;

所以,这是不可能的.如果希望它们的方法为internal,则AB不能实现I.

由于界面I的目的只是将常见功能组合在一起,因此您可以使用组合来解决这一问题.与AB直接实现I不同,它们可以具有类型为I的名为common(或者更好的名称)的属性,而B可以要求A来实现commonProperties.

abstract class B {
    internal abstract val common: I
    internal abstract fun doStuff()
}

A可以使用object实现这一点:

class A private constructor(): B() {
    override val commonProperties = object: I {
        override fun doOtherStuff() {
            // do other stuff
        }
    }

    override fun doStuff() {
        // ...
    }
}

您可以访问objectA中的几乎所有内容,因此您只需将这些常见功能的实现转移到object中即可.

你会说useI(A().common),而不是useI(A()).

Kotlin相关问答推荐

只能在元素区域中点击的Jetpack Compose列

Spring Boot kotlin协程不能并行运行

Kotlin扩展函数未调用Hibernate/JPA中的重写函数

如何在Spring Boot中注册新的集合工厂

Kotlin 说不需要强制转换,但删除后会出现新警告

为什么我的通用Kotlin函数中的这个转换未经判断?

为什么 Kotlin 在将协变类型参数转换为不变类型参数时会产生 Unchecked Cast 警告?

Android Jetpack Compose:在空的 Compose 活动中找不到 OutlinedTextField (Material3)

Kotlin:我可以将函数分配给 main 的伴随对象中的变量吗?

如何在 Kotlin 中不受约束?

compareBy 如何使用布尔表达式在 kotlin 中工作

Kotlin 可打包类抛出 ClassNotFoundException

如何在 IntelliJ 中更改 Kotlin 的this property has a backing field代码编辑器突出显示?

如何从不同的功能发出流量值? Kotlin 协程

如何在调试中修复 ClassNotFoundException: kotlinx.coroutines.debug.AgentPremain?

无法解决:androidx.lifecycle:lifecycle-extensions-ktx:2.0.0-alpha1

如果kotlin已经有了getter和setter,为什么在数据类中有componentN函数?

使用 rxbinding 时我应该取消订阅吗?

在 Kotlin 中声明 Byte 会出现编译时错误The integer literal does not conform to the expected type Byte

是否可以在不使用class的情况下将 Mockito 与 Kotlin 一起使用?