2016-12-24 73 views
2

我有一个嵌套的私有类的类。我有一个标准的Java构建器模式Builder,它构造了这个类的实例。我不希望我班以外的任何人能够看到我隐藏的课程。Kotlin嵌套成员的可见性

在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); } 
    } 
} 

但我无法弄清楚如何做相同的科特林:

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,加法器,vals等的构建器,然后在init中我构建了一个不可变的Example

我看到的唯一的选择是:

  1. 而不是在我的建设者一个SneakyType保存所有必要的信息,以构建一个,然后构造它Example。工程但增加了很多复杂性。
  2. 放弃Example是不可改变的,允许制造商调入它来建立一个Sneaky
  3. 揭露Sneaky

有没有办法模仿的Java版本?

回答

2

我看到两个可行方案:

  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只有你科特林编译模块中可见。

  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) 
         } 
        } 
    } 
    
+0

我同意第二个选项是非常好的。不幸的是,对我来说,我认为它不会很好地工作,因为我实际上有一个更复杂的数据结构,它只涉及一些'SneakyType'。第一种选择是我最终做的。为好的选项提供最高票数。没有标记“正确”,只是希望有人提出一个更好的主意。谢谢! –