【问题标题】: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(父级)有关,因此设计上是错误的。

标签: android kotlin


【解决方案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:

与实例方法和变量一样,内部类是关联的 具有其封闭类的实例并可以直接访问该类 对象的方法和字段。 另外,因为内部类是 与实例关联,它本身不能定义任何静态成员。

(由我突出显示)

出于同样的原因,将准静态伴随对象与实例关联是没有意义的。

解决方案(选择一个):

  1. 使用val(类似于final)。
  2. 将伴随对象移动到封闭类。
  3. 使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)。

但是,有两种方法可以选择(我选择了第一种):

  1. 使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
            }
        }
    }
    
  2. 在适配器中定义常量:

    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 绝对。这就是为什么我在回答的开头写了“不可能在内部类中添加常量”。
猜你喜欢
  • 1970-01-01
  • 2018-12-06
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 2010-10-03
  • 2021-12-17
  • 2014-11-07
  • 2017-10-01
相关资源
最近更新 更多