首页 > 解决方案 > 引用没有完全限定的嵌套对象

问题描述

我有如下代码(我控制的所有代码):

class FirstVeryLongName {
  object ObjectA
  object ObjectB
  object ObjectC
}
class SecondVeryLongName {
  object ObjectB
  object ObjectD
}

我需要编写的代码相当于

operation1(FirstVeryLongName.ObjectA, FirstVeryLongName.ObjectB)
operation2(SecondVeryLongName.ObjectB, SecondVeryLongName.ObjectD)

...除了重复使用很长的名称会增加很多混乱。

这是我希望能奏效的东西,但似乎没有:

FirstVeryLongName.run {
  operation1(ObjectA, ObjectB)
}

ObjectA...即使我尝试移动并ObjectB成为FirstVeryLongName写作的伴侣,我也无法完成工作

FirstVeryLongName.Companion.run { ... }

...我曾希望这会给对象提供无限制的访问权限,就像val伴随对象中的 a 一样。

我特别想避免的一件事是类型别名或将它们作为别名导入。我希望它在没有交叉引用或手动查看这些都来自的导入的情况下是显而易见的。

是否有一些技巧可以让我编写此代码并编写 FirstVeryLongName, ObjectA, 并且ObjectB每个都只写一次?

标签: kotlin

解决方案


对我来说,它不像你尝试的那样工作是有道理的。

类名本身不是实例,run因此with不适用。这与只写包名称相同,仅此而已。这也不起作用。

关于Companion- 方法,我假设您实现了以下内容:

class FirstVeryLongName {
  companion object {
    object ObjectA
    object ObjectB
    object ObjectC
  }
}

和一个用法,例如:

with(FirstVeryLongName.Companion) {
  operation1(ObjectA, ObjectB)
}

实际上,只要您为伴侣定义了此类属性(这也适用于函数),它就可以工作。其实这也是你自己提到的。object如果您还没有这样做,您可能想查看生成的字节码以查看实际对应的内容。如果你这样做了,你可以跳过本段的其余部分;-) 把它想象成它只是嵌套类。因此,在上面的示例中,我们在 -class 内部有 3 个嵌套类Companion,它们在FirstVeryLongName-class 内部。

在 Kotlin 中,对单例字段的访问对INSTANCE您是隐藏的。在 Kotlin 代码FirstVeryLongName.Companion.ObjectA中可以同时表示类型和单例实例引用。上下文是相关的。

由于您不能在run/中仅使用类名或导入语句的一部分with,因此您也不能以这种方式简化对单例实例的访问。

但是,您可以执行以下操作。注意:我显然不推荐这种方法(我不相信你真的需要: theobject和 the val)。也许你也可以在那里使用对象表达式?很可能有一种更简单的方法来构建您的代码,但如果没有适当的上下文,我只能猜测......我可能是错的):

class FirstVeryLongName {
  companion object {
    val ObjectA = FirstVeryLongName.ObjectA // can you use an object expression here?
    val ObjectB = FirstVeryLongName.ObjectA
    val ObjectC = FirstVeryLongName.ObjectA
  }
  object ObjectA
  object ObjectB
  object ObjectC
}

现在run/with可以按您的意愿工作,但现在它实际上访问了val指向的 -reference object

with(FirstVeryLongName.Companion) {
  operation1(ObjectA, ObjectB)
}

只是显示一个使用对象表达式的简单示例。你可能想要一个通用的超类、接口,或者,如果你不介意,你甚至可以object : Any()在这里使用:

class FirstVeryLongName {
  companion object {
    val ObjectA = object : interfaces.ObjectA  { /* ... */ }
    // ...
  }
}

用法看起来仍然相同。现在只有签名operation1可能不同。


推荐阅读