【问题标题】:Kotlin secondary constructorKotlin 二级构造函数
【发布时间】:2013-10-10 15:07:32
【问题描述】:

如何在 Kotlin 中声明辅助构造函数?

有相关的文档吗?

以下不编译...

class C(a : Int) {
  // Secondary constructor
  this(s : String) : this(s.length) { ... }
}

【问题讨论】:

    标签: syntax constructor kotlin


    【解决方案1】:

    更新:由于 M11 (0.11.*) Kotlin 支持secondary constructors


    目前 Kotlin 仅支持主构造函数(以后可能会支持辅助构造函数)。

    二级构造函数的大多数用例都通过以下技术之一解决:

    技术 1.(解决你的问题)在你的类旁边定义一个工厂方法

    fun C(s: String) = C(s.length)
    class C(a: Int) { ... }
    

    用法:

    val c1 = C(1) // constructor
    val c2 = C("str") // factory method
    

    技术2.(也可能有用)定义参数的默认值

    class C(name: String? = null) {...}
    

    用法:

    val c1 = C("foo") // parameter passed explicitly
    val c2 = C() // default value used
    

    请注意,默认值适用于任何函数,不仅适用于构造函数

    技术 3.(当你需要封装时)使用在伴随对象中定义的工厂方法

    有时你希望你的构造函数是私有的,并且只有一个工厂方法可供客户端使用。目前这只能通过 companion object 中定义的工厂方法实现:

    class C private (s: Int) {
        companion object {
            fun new(s: String) = C(s.length)
        }
    }
    

    用法:

    val c = C.new("foo")
    

    【讨论】:

    • 如果从不支持辅助构造函数,则应重命名主构造函数。 ;)
    • Andrey Breslav,我认为在 Kotlin 中放弃对辅助构造函数的支持是一个坏主意,因为这些构造函数有时是必需的,尤其是在使用 Java 框架和扩展 Java 类时。希望你能尽快把它们拿回来。
    • 这很有趣:二级构造函数返回了:)
    • 在 M11 中添加了辅助构造函数。
    • 是否仍被认为是使用有效 Java 中描述的静态工厂方法的最佳实践?还是现在不需要了?我想如果您预见到需要控制实例,您将总是希望使用静态工厂。
    【解决方案2】:

    作为documentation points,您可以通过这种方式使用辅助构造函数

    class GoogleMapsRestApiClient constructor(val baseUrl: String) {
    
        constructor() : this("https://api.whatever.com/")
    
    }
    

    记住你必须扩展第一个构造函数的行为。

    【讨论】:

    • 不是直接从第二个构造函数扩展第一个构造函数,而是可以委托给另一个辅助构造函数,这已经做到了:
    • 我认为这个更适合当前情况:` class GoogleMapsRestApiClient constructor(val baseUrl: String = "api.whatever.com/") { //class body } `
    • 是的!但这不是问题的背景^^如果你有更好的建议,我可以编辑它。感谢@AlexanderKrol 的呐喊
    【解决方案3】:

    要声明一个二级构造函数 Kotlin 只需使用 constructor 关键字:like

    这是一个主构造函数:

    class Person constructor(firstName: String) {
    
    }
    

    class Person(firstName: String) {
    
    }
    

    二级构造函数代码如下:

    class Person(val name: String) {
        constructor(name: String, parent: Person) : this(name) {
            parent.children.add(this)
        }
    }
    

    必须调用主构造函数,否则编译器会抛出以下错误

    Primary constructor call expected
    

    【讨论】:

      【解决方案4】:

      init 的构造函数:

      class PhoneWatcher : TextWatcher {
      
          private val editText: EditText
          private val mask: String
      
          private var variable1: Boolean = false
          private var variable2: Boolean = false
      
          init {
              variable1 = false
              variable2 = false
          }
      
          constructor(editText: EditText) : this(editText, "##-###-###-####")
      
          constructor(editText: EditText, mask: String) {
              this.editText = editText
              this.mask = mask
          }
          ...
      }
      

      【讨论】:

        【解决方案5】:

        您可以在 Kotlin 中使用 constructor 定义多个构造函数,但您需要跳过默认构造函数 class AuthLog(_data: String)

        class AuthLog {
        
            constructor(_data: String): this(_data, -1)
        
            constructor(_numberOfData: Int): this("From count ", _numberOfData)
        
            private constructor(_data: String, _numberOfData: Int)
        
        }
        

        For more details see here

        更新

        现在你可以定义默认构造函数了

        class AuthLog(_data: String, _numberOfData: Int) {
        
            constructor(_data: String): this(_data, -1) {
                //TODO: Add some code here if you want
            }
        
            constructor(_numberOfData: Int): this("From count", _numberOfData)
        
        }
        

        【讨论】:

          【解决方案6】:

          Android 中具有多个构造函数的自定义视图示例:

          class ShaderBackground : View {
          
          
              constructor(context: Context) : super(context) {
                  init()
              }
          
              constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
                  init()
              }
          
              constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
                  context,
                  attrs,
                  defStyleAttr
              ) {
                  init()
              }
          
              private fun init() {
          
                 // Init stuff here
                  paint = Paint();
                  paint.strokeWidth = 10f;
                  paint.style = Paint.Style.FILL_AND_STROKE;
          
              }
          

          【讨论】:

          • 为 korlin 文件创建构造函数的任何快捷方式我尝试了 ALT+INSERT 但没有显示任何用于生成构造函数的菜单。 能否分享一下 kotlin POJO 生成构造函数的快捷方式?
          • @Arbaz.in 为类生成构造函数 在“代码”菜单上,单击“生成”⌘N。在 Generate 弹出窗口中,单击 Constructor for Kotlin。如果类中包含字段,选择构造函数需要初始化的字段,点击确定。
          【解决方案7】:

          回答为时已晚,但这是我的微薄贡献:)

          由于 Kotlin 支持默认参数值,(注意:我想使用 null 的幂)像这样:

          data class MyClass(val a: Int? = null, val b: String? = null, val c: Double? = null)
          

          我们不需要有多个构造函数。但即使我们想要它,我们也可以这样做:

          data class MyClass(val a: Int?, val b: String?, val c: Double?){
              constructor() : this(null,null,null)
              constructor(a : Int) : this(a,null,null)
              constructor(a : Int, b: String) : this(a,b,null)
          }
          

          我们可以通过以下方式实例化这个类:

          println(MyClass().toString())
          println(MyClass(1).toString())
          println(MyClass(1,"String").toString())
          println(MyClass(1,"String",0.5).toString())
          

          让我们也看看结果:

          【讨论】:

            【解决方案8】:

            我刚看到这个问题,我认为可能还有另一种听起来比 Andrey 提出的方法更好的技术。

            class C(a: Int) {
                class object {
                    fun invoke(name: String) = C(name.length)
                }        
            }
            

            您可以编写val c:C = C(3)val c:C = C("abc") 之类的内容,因为invoke 方法的工作方式与apply 方法在Scala 中的工作方式相同。

            更新

            到目前为止,辅助构造函数已经是语言规范的一部分,因此不应使用此解决方法。

            【讨论】:

            • 辅助构造函数(自 M11 起)比这个选项更好。
            • 我在 M11 发布之前就回答了这个问题,投反对票很卑鄙,你为什么不尝试编辑答案?
            • 我无法编辑答案,因为我的编辑不会与您的答案一致。我不同意这应该被建议。删除你的答案会阻止我投反对票。
            • 也许在 M11 之前它是一个有用的 hack,但现在不是,也不应该在这里。如果你离开它,你会邀请新的反对票。保持你的旧帖子更新,你不会遇到这个。 meta.stackexchange.com/a/121351/312466
            【解决方案9】:

            下面的代码 sn-p 应该可以工作

            class  C(a:Int){
              constructor(s:String):this(s.length){..}
            }
            

            【讨论】:

              【解决方案10】:
              class Person(val name: String) {
                  constructor(name: String, parent: Person) : this(name) {
                      parent.children.add(this)
                  }
              }
              

              你可以试试这个。

              【讨论】:

                【解决方案11】:

                我对大多数答案感到有些困惑。 为了便于理解,我添加了一个包含更多元素的示例:

                   @JsonInclude(JsonInclude.Include.NON_NULL)
                   data class Response(val code: String) {
                      var description: String? = null
                      var value: String? = null
                
                      constructor(code: String, description: String?) : this(code) {
                          this.description = description
                      }
                
                      constructor(code: String, description: String?, value: String) : this(code, description) {
                          this.value = value
                      }
                   }
                

                【讨论】:

                  【解决方案12】:

                  kotlin 二级构造函数示例

                  class Person(name: String){
                      var name=""
                      var age=0
                  
                      constructor(age :Int,name : String)  : this(name){
                          this.age=age
                          this.name=name
                      }
                      fun display(){
                          print("Kotlin Secondary constructor $name  , $age")
                      }
                  }
                  

                  主要功能

                  fun main(args : Array<String>){
                  
                      var objd=Person(25,"Deven")
                      objd.display()
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    使用变量“内部”,然后您可以在单个类中添加多个构造函数,如下所示。这将完美无缺。

                    class AuthModel {
                    var code: String? = null
                    
                    internal constructor(code: String?) {
                        this.code = code
                    }
                    
                    internal constructor() {}
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 2019-06-02
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-03-18
                      • 1970-01-01
                      • 2019-01-10
                      • 2018-04-23
                      相关资源
                      最近更新 更多