【问题标题】:Kotlin visibility of nested members嵌套成员的 Kotlin 可见性
【发布时间】:2016-12-28 05:45:57
【问题描述】:

我有一个带有嵌套私有类的类。我有一个 Builder,标准的 Java 构建器模式,它构造了这个类的实例。我不希望班级以外的任何人看到我的隐藏班级。

在 Java 中我可以这样做:

public class Example {
    private SneakyType doNotExposeThis;

    private Example(Builder builder) {
        // OK 'cause in Java you can access the private
        // members of a nested class
        doNotExposeThis = builder.doNotExposeThis;
    }

    private static class SneakyType {
        SneakyType(String x) {
            // stuff
        }
    }

    public static class Builder {
        private SneakyType doNotExposeThis;

        public void addFoo(String something) {
            doNotExposeThis = new SneakyType(something);
        }

        public Example build() { return new Example(this); }
    }
}

但我不知道如何在 Kotlin 中做同样的事情:

class Example(builder: Builder) {
    private lateinit var doNotExposeThis: SneakyType

    init {
        doNotExposeThis = builder.doNotExposeThis
    }

    class Builder {
        // If private or internal I can't access it in Example.init
        // and if public it gets exposed. 
        val doNotExposeThis: SneakyType


        fun addFoo(something: String) {
            // actual construction is quite a bit more complex
            doNotExposeThis = SneakyType(something)
        }
    }
}

请注意,为了 Java 互操作,我想保留我的构建器。我也想要它,因为我的对象构造起来很复杂,而且我希望它是不可变的,所以我有一个包含许多 setter、adders、val 等的构建器,然后在init 中构造一个不可变的Example

我看到的唯一选择是:

  1. 不要在我的构建器中使用SneakyType,而是保存构建它所需的所有信息,然后在Example 中构建它。有效,但增加了很多复杂性。
  2. 放弃Example 是不可变的,并允许构建器调用它来设置Sneaky
  3. 公开Sneaky

有没有办法模仿Java版本?

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    我看到了两个可行的选择:

    1. 使用internalvisibility modifier

      class Example private constructor(builder: Builder) {
          private val doNotExposeThis: SneakyType
      
          init {
              doNotExposeThis = builder.doNotExposeThis
          }
      
          internal class SneakyType(x: String)
      
          class Builder {
              internal lateinit var doNotExposeThis: SneakyType
      
              fun addFoo(something: String) {
                  doNotExposeThis = SneakyType(something)
              }
      
              fun build(): Example {
                  return Example(this)
              }
          }
      }
      

      这将使SneakyType 仅在您的 Kotlin 编译模块中可见。

    2. 使Example 独立于其构建器(这是我推荐的):

      class Example private constructor(private val doNotExposeThis: SneakyType) {
          private class SneakyType(x: String)
      
          class Builder {
              private lateinit var doNotExposeThis: SneakyType
      
              fun addFoo(something: String) {
                  doNotExposeThis = SneakyType(something)
              }
      
              fun build(): Example {
                  return Example(doNotExposeThis)
              }
          }
      }
      

    【讨论】:

    • 我同意第二个选项非常好。不幸的是,对我来说,我不认为它工作得很好,因为我实际上有一个更复杂的数据结构,它只涉及一些像SneakyType 这样的东西。第一个选项是我最终做的。对好的选择投了赞成票。尚未标记“正确”,希望有人提出更好的主意。谢谢!
    猜你喜欢
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 2011-08-05
    • 2013-06-22
    • 2018-09-22
    相关资源
    最近更新 更多