在Kotlin中,接口是否有办法拥有关联的类型协定?

时间:2019-10-03 22:45:13

标签: swift kotlin

在Swift中,您可以编写如下内容:

#%%
from pymodelica import compile_fmu
from pyfmi import load_fmu
import matplotlib.pylab as plt

#%%
model_name = 'friction1D.fricexample_1'
mofile = 'friction1D.mo'

#%%
fmu_name = compile_fmu(model_name, mofile)
sim = load_fmu(fmu_name)

#%%
opts = sim.simulate_options()
opts["ncp"] = 500
opts['CVode_options']['rtol'] = 1.0e-8
res = sim.simulate(final_time=10, options=opts)

#%%
time = res['time']
vel = res['v']
ffo = res['ffo']
sfo = res['sfo']

#%%
plt.plot(time, vel)
plt.xlabel("Time (s)")
plt.ylabel("Velocity (m/s)")
plt.show()

#%%
plt.plot(time, ffo, label="friction force")
plt.plot(time, sfo, label="shear force")
plt.xlabel("Time (s)")
plt.ylabel("Force (N)")
plt.legend()
plt.show()

通过这种方式,如果结构或类符合协议protocol Constants { associatedtype StringProperties } struct ViewState { let viewName: String } extension ViewState: Constants { enum StringProperties: String { case text = "some view text" } } struct LayerState { let layerName: String } extension LayerState: Constants { enum StringProperties: String { case text = "some layer text" } } let viewState = ViewState(viewName: "Some view name") let viewValue = ViewState.StringProperties.text.rawValue // "some view text" let layerState = LayerState(layerName: "Some layer name") let layerValue = LayerState.StringProperties.text.rawValue // "some layer text" ,则它必须实现与Constants相关的某些事情

StringConstants中是否有类似的东西会从接口强制这种一致性?

最好执行以下操作:

Kotlin

1 个答案:

答案 0 :(得分:0)

在Kotlin(以及Java)中,枚举在编译时定义为单例。这就是为什么您不能在它们上使用变量的原因。仅预定义的静态值。

在你有这个枚举

enum class MyEnum(val text: String) {
    MyValue("some text")
}

你叫它

val myEnum = MyEnum.MyValue

每次您都有相同的对象。

在其他类中声明的所有枚举都是static(关于静态关键字为here is the question on stackoverflow),这意味着它们在运行时不依赖于对象,而在编译时依赖于类。

data class MyClass {
   enum class MyEnum {
       ...
   }
}

将编译为:

public class MyClass {

   public static enum MyEnum {
      ...
   }
}

这就是为什么不能在它们上使用inner修饰符的原因:

inner enum class is not allowed

要获得所需的结果,您有两种选择:

1)使用属性:

interface Constants {
   val text: String
}

// data classes are final and cannot be extended later
data class ViewState(val viewName: String) : Constants {
    override val text = "some view text"
}

data class LayerState(val layerName: String) : Constants {
    override val text = "some layer text"
}

2)定义两个不同的枚举(无接口):

data class ViewState(val viewName: String) {
    enum class StringProperties(val string: String) {
        Text("some view text")
    }
}

data class LayerState(val layerName: String) {
    enum class StringProperties(val string: String) {
        Text("some layer text")
    }
}

这样,您可以按原样使用它,而无需使用Constants界面

val viewText = ViewState.StringProperties.Text.string // "some view text"
val layerText = LayerState.StringProperties.Text.string // "some layer text"

编辑:

Kotlin支持extensions,但不会修改您的课程。而是创建了以您的对象作为参数的新方法:

fun MyObject.extensionFunc() {
   // do stuff
}

将编译为

public void extensionFunc(MyObject $receiver) {
    // do stuff
}

编辑2:

我再次无意中发现了您的问题,再三考虑了一下,我想为您提供一个解决方案:AdapterViewHolder如何在RecyclerView android lib中捆绑在一起。 / p>

interface Adapter<T : Adapter.ViewHolder> {

    fun doSmth(viewHolder: T)

    interface ViewHolder
}

每当要实现Adapter时,还必须实现ViewHolder

class AdapterImpl : Adapter<AdapterImpl.MyViewHolder> {

    override fun doSmth(viewHolder: MyViewHolder) {
    }

    class MyViewHolder : Adapter.ViewHolder {
    }
}

我希望这是您一直在寻找的东西!