swift中的继承和初始化

时间:2015-04-17 17:57:52

标签: swift inheritance initializer

我一直在尝试创建两个不同的类:对于超类,我使用适当的参数创建属性和init()函数。但是,当我使用自己的属性和init()函数创建我的子类时,我遇到了麻烦。

我在这里想要实现的是,在我的应用程序的某个时刻,用户将输入一堆字段,当他/她准备好并点击“准备好”按钮时,字段的内容将是用作我的子类的init()函数的参数。超类的init()的参数少于子类的init()。

我一直在阅读指定和便利初始化器,但我有点困惑。也许我真的不需要它们,我不确定。

我想避免的是在调用init()之后必须手动更改子类的任何属性的值。

非常感谢任何帮助。

///新代码:

班级习惯{

enum HabitType {
    case health
    case wealth
    case social
    case career
    case noType
}

var habitID: Int
var title: String
var type: HabitType
var duration: Int
var toAccomplish = [String]()
var currentFeelings = [String]()
var howToFix = [String]()

init?(habitID: Int, title: String, type: String, duration: Int, toAccomplish: [String]?, currentFeelings: [String]?, howToFix: [String]?) {

    self.habitID = habitID
    self.title = title
    switch type {
    case "health":
        self.type = HabitType.health
    case "wealth":
        self.type = HabitType.wealth
    case "social":
        self.type = HabitType.social
    case "career":
        self.type = HabitType.career
    default:
        self.type = HabitType.noType
    }
    self.duration = duration

    if let accomplish = toAccomplish {
        self.toAccomplish = accomplish
    }
    if let feelings = currentFeelings {
        self.currentFeelings = feelings
    }
    if let fix = howToFix {
        self.howToFix = fix
    } else {
        return nil
    }
}

}

class MiniHabit:习惯 {

var trigger: String
var action: String

init(habitID: Int, title: String, type: String, duration: Int, toAccomplish: [String]?, currentFeelings: [String]?, howToFix: [String]?, trigger: String, action: String) {

    ////init() Error: A non-failable initializer cannot chain to failable initializer 'init(habitID:title:type:duration:toAccomplish:currentFeelings:howToFix:)' written with 'init?' 
    super.init(habitID: habitID, title: title, type: type, duration: duration, toAccomplish: toAccomplish, currentFeelings: currentFeelings, howToFix: howToFix)

    self.trigger = trigger
    self.action = action

}

}

3 个答案:

答案 0 :(得分:4)

我对您的代码进行了一些更改,这就是现在的样子:

// 1.
class Habit {
    var habitID: Int
    var title: String
    var type: String
    var duration: Int
    var toAccomplish = [String]()
    var currentFeelings = [String]()
    var howToFix = [String]()

    init(habitID: Int, title: String, type: String, duration: Int, toAccomplish: [String]?, currentFeelings: [String]?, howToFix: [String]?) {

        self.habitID = habitID
        self.title = title
        self.type = type
        self.duration = duration

        // 2.
        if let acomplish = toAccomplish {
            self.toAccomplish = acomplish
        }

        if let feelings = currentFeelings {
            self.currentFeelings = feelings
        }

        if let fix = howToFix {
            self.howToFix = fix
        }
    }

    class MiniHabit: Habit {
        // 3.
        var trigger: String
        var action : String

        init(habitID: Int, title: String, type: String, duration: Int, toAccomplish: [String]?, currentFeelings: [String]?, howToFix: [String]?, trigger: String, action: String) {
            // 4.
            self.trigger = trigger
            self.action = action

            super.init(habitID: habitID, title: title, type: type, duration: duration, toAccomplish: toAccomplish, currentFeelings: currentFeelings, howToFix: howToFix)
        }
    }
}

1。可能不需要将您的课程声明为公开。来自文档:

  

公共访问允许实体在其定义模块的任何源文件中使用,也可以在另一个导入定义模块的模块的源文件中使用。在指定框架的公共接口时,通常使用公共访问。

默认情况下,您的类将具有internal访问权限,如果您不打算从这些类创建框架,这应该没问题。

有关详细信息,请参阅 Swift编程语言中的访问控制,请在此处链接:https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html

2. 使用if let使用可选绑定比检查可选项是否为n然后强制解包它更可取。有关可选绑定的更多信息,请参阅 Swift编程语言

3。 triggeraction只要您在之前设置,就不必为其提供空字符串的初始值打电话给super init。 Swift强制要求在调用super.init之前初始化当前类中定义的所有属性。因为您是在super.init来电之前设置的,所以如果您希望它们是不可变的,也可以使用let代替var代替triggeraction

4。您现在只是初始化MiniHabit定义的变量,所有其他变量都由Habitat上的指定初始化设置。

另外,我注意到type中有一个Habit变量。如果type只应该选择少数几个值,我建议使用enum,例如:

class Habit {
    enum HabitType {
        // Give these more appropriate names.
        case HabitType1
        case HabitType2
        case HabitType3
    }

    var type: HabitType

    // Other variables...
}

希望有所帮助。

答案 1 :(得分:1)

您的代码存在问题:

  1. 初始值设定项中不需要required关键字。如documentation
  2. 中所述
      

    在类初始化程序的定义之前编写required修饰符,以指示该类的每个子类都必须实现该初始化程序

    1. 不应在子类
    2. 中分配在超类'初始值设定项中指定的属性

      此代码适用于Playground(Xcode 6.3):

      public class Habit {
          var habitID: Int
          var title: String
          var type: String
          var duration: Int
          var toAccomplish = [String]()
          var currentFeelings = [String]()
          var howToFix = [String]()
      
          public init(habitID: Int, title: String, type: String, duration: Int, toAccomplish: [String]?, currentFeelings: [String]?, howToFix: [String]?) {
      
              self.habitID = habitID
              self.title = title
              self.type = type
              self.duration = duration
      
              if toAccomplish != nil {
                  self.toAccomplish = toAccomplish!
              }
              if currentFeelings != nil {
                  self.currentFeelings = currentFeelings!
              }
              if howToFix != nil {
                  self.howToFix = howToFix!
              }
          }
      }
      
      public class MiniHabit: Habit {
          var trigger: String = ""
          var action: String = ""
      
          public init(habitID: Int, title: String, type: String, duration: Int, toAccomplish: [String]?, currentFeelings: [String]?, howToFix: [String]?, trigger: String, action: String) {
              super.init(habitID: habitID, title: title, type: type, duration: duration, toAccomplish: toAccomplish, currentFeelings: currentFeelings, howToFix: howToFix)
      
              self.trigger = trigger
              self.action = action
          }
      }
      
      var h = MiniHabit(habitID: 0, title: "", type: "", duration: 1, toAccomplish: nil, currentFeelings: nil, howToFix: nil, trigger: "", action: "")
      

答案 2 :(得分:1)

响应更新代码的新答案

它看起来比上次好,但仍然可以做出一些改变:

首先,您不需要使用switch语句来检查哪个枚举类型type应该是。您可以使用枚举类型作为参数传递给初始化器。例如,假设这是您的Habit类:

class Habit {
    enum HabitType {
        case Health
        case Wealth
        case Social
        case Career
    }

    let type: HabitType

    // Don't use a String here, use the HabitType enum.
    init(type: HabitType) {
        self.type = type
    }
}

然后您可以像这样创建一个习惯实例:

let aHabit = Habit(type: .Health)

有关详细信息,请参阅 Swift编程语言中的枚举

其次,关于您的HabitType枚举,我发现您有一个案例NoType。这将是使用选项而不是使用NoType的理想场所。例如,您可以将变量type声明为可选,然后当它等于nil时,您知道没有类型。例如,这将是您的HabitType枚举:

enum HabitType {
    case Health
    case Wealth
    case Social
    case Career
}

// And this is how could could define type to be optional.
let type: HabitType?

第三,您在MiniHabit初始化程序中遇到的错误是因为您已声明Habit的初始化程序可用(由{{表示) 1}} ?之后。在这种情况下,这不是必需的,而您的初始化设备可能如下所示:

init

有关可用初始化工具的详细信息,请参阅此处:https://developer.apple.com/swift/blog/?id=17

希望有所帮助!如果还有其他需要澄清的话,请告诉我。