如何在内部类中定义常量?
Posted
技术标签:
【中文标题】如何在内部类中定义常量?【英文标题】:How do I define constants in an inner class? 【发布时间】:2020-01-15 06:05:01 【问题描述】:我有以下 Java 代码,我想将其转换为 Kotlin:
class RideHistoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
class HistoryItemHolder extends RecyclerView.ViewHolder
private static final int TYPE_IN_PROGRESS = 1
private static final int TYPE_CANCELLED = 2
private static final int TYPE_FINISHED = 3
// class methods and properties are written
我想出了以下代码:
class RideHistoryAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>()
private inner class HistoryItemHolder(view: View)
: RecyclerView.ViewHolder(view)
private companion object
private const val TYPE_IN_PROGRESS = 1
private const val TYPE_CANCELLED = 2
private const val TYPE_FINISHED = 3
// class methods and properties are written
android Studio 在companion object
行的“对象”下方显示红色波浪线,表示:
此处不允许伴随对象
注意:我知道我可以将其转换为非内部类,但我更愿意保留它。我还检查了我也不能在内部类中定义接口。
【问题讨论】:
您有什么特别的理由要使用内部类吗? @NatigBabayev 避免显式传递适配器的属性(内部类减少了额外的调用和值的维护)。 那为什么不把伴生对象移到父类呢? @NatigBabayev 是的,我可以这样做,但由于它与 HistoryItemHolder(内部类)而不是 RecyclerVIew(父级)有关,因此设计上是错误的。 【参考方案1】:首先你的 Java 是无效的。如果你修复它,你会得到一个错误:Inner classes can not have static declarations
您不能在内部类中拥有伴随对象,原因与您不能拥有 static
members in an inner class in java 的原因相同
https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html:
与实例方法和变量一样,内部类是关联的 具有其封闭类的实例并可以直接访问该类 对象的方法和字段。 另外,因为内部类是 与实例关联,它本身不能定义任何静态成员。
(由我突出显示)
出于同样的原因,将准静态伴随对象与实例关联是没有意义的。
解决方案(选择一个):
-
使用
val
(类似于final
)。
将伴随对象移动到封闭类。
使HistoryItemHolder
不是内部类。
【讨论】:
谢谢。我意识到我的错误。我一定写过public static final int TYPE_IN_PROGRESS = 1;
。现在这是一个有效的 Java 代码。
我尝试了您的解决方案,但它没有转换 public static final
行的 Java 代码 (using this answer),而是转换为 private final
(没有静态意味着它绑定到类的实例而不是课程,因此不是一个好习惯)。
如果你想拥有它static final
(在伴随对象中相当于const
)你必须将伴随对象移动到外部类,原因在我的回答中给出。旁注:我认为private final
字段是一个很好的解决方案。从语义上讲,它的含义非常清楚。
是的,它会起作用,但不是一个优雅的解决方案 (here's why)。使类非内部(如@NatigBabayev 所建议)似乎是该问题的唯一有效解决方案。我想我达到了 Kotlin 的罕见极限。
好点,这是解决问题的第三种方法。我会把它添加到我的答案中。【参考方案2】:
我可以确认无法在内部类中添加常量(请参阅 Kotlin 论坛上的 my question)。
但是,有两种方法可以选择(我选择了第一种):
使ViewHolder
成为一个非内部类——这意味着它不能再访问适配器的方法/属性:
public class Adapter
public class ViewHolder(private val adapter: Adapter)
private companion object
private const val TYPE_IN_PROGRESS = 1
private const val TYPE_CANCELLED = 2
private const val TYPE_FINISHED = 3
在适配器中定义常量:
public class Adapter
private const val TYPE_IN_PROGRESS = 1
private const val TYPE_CANCELLED = 2
private const val TYPE_FINISHED = 3
public class ViewHolder(private val adapter: Adapter)
// ..
注意:不要将您的 const val
转换为 val
,因为它会将其绑定到您的类实例(这很糟糕。More about it here)。
【讨论】:
这里的第二种方式只是工作,因为适配器不是内部类,你应该得到编译错误Const 'val' are only allowed on top level or in objects
@BabyishTank 绝对。这就是为什么我在回答的开头写了“不可能在内部类中添加常量”。以上是关于如何在内部类中定义常量?的主要内容,如果未能解决你的问题,请参考以下文章