我一直在尝试创建两个不同的类:对于超类,我使用适当的参数创建属性和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
}
}
答案 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。 trigger
和action
只要您在之前设置,就不必为其提供空字符串的初始值打电话给super init。 Swift强制要求在调用super.init
之前初始化当前类中定义的所有属性。因为您是在super.init
来电之前设置的,所以如果您希望它们是不可变的,也可以使用let
代替var
代替trigger
和action
。
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)
您的代码存在问题:
required
关键字。如documentation:在类初始化程序的定义之前编写
required
修饰符,以指示该类的每个子类都必须实现该初始化程序
此代码适用于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
希望有所帮助!如果还有其他需要澄清的话,请告诉我。