【问题标题】:Kotlin – Why parameter values have to be passed in sub classes?Kotlin – 为什么必须在子类中传递参数值?
【发布时间】:2019-06-20 09:34:12
【问题描述】:

我的代码:

open class Club(name: String, country: String)

class FemaleClub(): Club()

var femaleClub = FemaleClub("Blue", "Australia")

为什么上面的代码不可能?

为什么会报错

没有为参数名称传递值

没有为参数国家/地区传递值

在我的子类中?这些值是在我启动 femaleClub 时设置的。

【问题讨论】:

  • 如果你的类的主体是空的,你可以省略括号 {},使代码更短:)

标签: class kotlin subclass subclassing


【解决方案1】:

您需要从要继承的类中调用构造函数(主/次)。

Club 只有一个构造函数,即主构造函数。它接受两个字符串作为参数。 Club 没有空的构造函数。

所以,它不能被调用为Club()

我会提出两项更改。

1) 将namecountry 设为Club 属性

open class Club(name: String, country: String)

2) 在FemaleClub的主构造函数中声明参数

由于您希望在实例化 FemaleClub 时能够为 namecountry 指定值,因此最好将 FemaleClub 的主构造函数提供给 namecountry 作为参数.

此外,我建议在传递值时使用命名参数,因为您可以轻松混淆两个字符串(导致将名称作为国家/地区传递,将国家/地区作为名称传递。

class FemaleClub(name: String, country: String): Club(name = name, country = country)

【讨论】:

    【解决方案2】:

    关于 Kotlin 类和继承,请阅读此处Classes and Inheritance 和此处Kotlin Inheritance

    您至少可以使用四种方法来获得您想要的:

    第一种方法 (default values):

    open class Club(var name: String = "Blue", var country: String = "Australia") {  }
    
    public class FemaleClub(): Club() {  }
    
    fun main() { 
        var femaleClub = FemaleClub()
        println("RESULT: ${femaleClub.country}")
    }
    
    // RESULT: Australia
    

    第二种方法(passing values):

    open class Club(var name: String, var country: String) {  }
    
    class FemaleClub(): Club("Green", "NZ") {  }
    
    fun main() {
        var femaleClub = FemaleClub()
        println("RESULT: ${femaleClub.country}")
    }
    
    // RESULT: NZ
    

    第三种方法 (init block):

    open class Club(name: String, country: String) {  
    
        var name: String = "Blue"
        var country: String = "Australia"
    
        init {
            this.name = name
            this.country = country 
        }
    }
    
    class FemaleClub(): Club("Green", "NZ") {  }
    
    fun main() {
        var femaleClub = FemaleClub()
        println("RESULT: ${femaleClub.country}")
    }
    
    // RESULT: NZ
    

    第四种方法 (class sec.constructor):

    open class Club {  
    
        var name: String
        var country: String
    
        constructor(name: String = "Blue", country: String = "Australia") {
            this.name = name
            this.country = country
        }
    }
    
    class FemaleClub(): Club() {  }
    
    fun main() {
        var femaleClub = FemaleClub()
        println("RESULT: ${femaleClub.country}")
    }
    
    // RESULT: Australia
    

    【讨论】:

    • 好吧,我不会用它们。
    • thx 伙计,让答案阅读起来更愉快。祝你有美好的一天:)
    【解决方案3】:

    在您的示例中,父类 Club 具有 主构造函数,根据语言规范,必须从同一类的 辅助构造函数 调用子类的主构造函数,用于初始化主构造函数中定义的参数。如果您不想从子类调用父类的主构造函数,您有几个选择:

    1. 主构造函数的参数设置默认值:

      open class Club(name: String = "DefaultName", country: String = "Country") {
      }
      

      在这种情况下,您将无法使用参数调用 主构造函数

      // this is not possible
      var femaleClub = FemaleClub("Blue", "Australia")
      
    2. 在调用主构造函数的父类中创建二级构造函数

      open class Club(name: String, country: String) {
      
          constructor(): this("Name", "Country")
      }
      

      但是你也不能打电话给FemaleClub("Blue", "Australia")

    为了能够使用子类FemaleClub("Blue", "Australia")的参数调用构造函数,您需要在子类的主构造函数中显式定义它们并调用父类的主构造函数,即:

    class FemaleClub(name: String, country: String): Club(name, country) {}
    

    【讨论】:

      【解决方案4】:

      FemaleClub 中,您没有指定应该传递给Club 的内容作为它的2 个String 参数namecountry

      而且您没有指定 FemaleClub 将 2 个字符串作为构造函数参数的任何地方,因此最后一行也不起作用。

      【讨论】:

        【解决方案5】:

        您的代码存在一些问题:

        • FemaleClub 没有接受两个参数的构造函数,即使基类有一个。

        • 继承类的主构造函数应该调用基类的主构造函数。因为您的基类接受两个不可为空的参数,所以您必须将它们提供给它,否则您的代码将无法编译。

        这些问题可以通过以下方式解决:

        class FemaleClub(name: String, country: String): Club(name, country) {
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-08-01
          • 1970-01-01
          • 2017-11-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-06
          • 2017-03-13
          相关资源
          最近更新 更多