为什么我在结构中的self.init调用之前得到错误'self'?

时间:2017-05-25 12:34:08

标签: swift

我已经构建了这个struct来处理我计划在某些自定义类中使用的特定类型的数据。
我的问题是featureSubSet变量能够成为少数枚举之一,当这个结构初始化时,它不会知道它将是哪个枚举,所以我将其声明为Any。

当调用public init时,它会适当地将数据汇集到所需的私有init方法,以便可以正确且完全地初始化它。

我在公共init方法结束时收到错误,但我不确定如何让它消失。

struct Feature {
//MARK: Variables needed for Feature
var featureSet: FeatureType
var featureSubSet: Any
var effect: String
var active: Bool?
var skill: Skill?
var ability: Ability?

public init(base: String, sub: String, effect: String, skill: Skill? = nil, ability: Ability? = nil) {
    switch base {
    case featureCategoryList()[0]: // Character Features
        self.init(CharacterFeature: sub, effect: effect)
    case featureCategoryList()[1]: // Combat Features
        self.init(CombatFeature: sub, effect: effect)
    case featureCategoryList()[2]: //Skill Features
        guard let newSkill = skill else {
            print("No skill")
            return
        }
        self.init(SkillFeature: sub, effect: effect, skill: newSkill)

    default:
        print("Somehow you picked something not on the list.")
        break
    }
}

private init(CharacterFeature sub: String, effect: String) {
    self.featureSet = .CharacterFeatures
    self.featureSubSet = CharacterFeatures.init(rawValue: sub)!
    self.effect = effect
}

private init(CombatFeature sub: String, effect: String) {
    self.featureSet = .CombatFeatures
    self.featureSubSet = CharacterFeatures.init(rawValue: sub)!
    self.effect = effect
}

private init(SkillFeature sub: String, effect: String, skill: Skill) {
    self.featureSet = .SkillFeatures
    self.featureSubSet = CharacterFeatures.init(rawValue: sub)!
    self.skill = skill
    self.effect = effect
}

//MARK: Feature functions
func string() -> String {
    //TODO: Make a string output for what the feature is.
    return ""
}
}

2 个答案:

答案 0 :(得分:3)

这是一种不正确的方法。如果你发现自己存储的内容为Any,那么你几乎肯定会走错路。探索这段代码是很困难的,因为它定义了很多其他类型,但是看一下,目前还不清楚为什么你需要AnyfeatureSubSet始终为CharacterFeatures类型。枚举的所有值都是相同的“类型”。

您在此处有错误:

    case featureCategoryList()[2]: //Skill Features
        guard let newSkill = skill else {
            print("No skill")
            return
        }

在这里:

    default:
        print("Somehow you picked something not on the list.")
        break
    }

返回时不会初始化self(可能是您的问题)。如果您可能失败,那么您需要将其设置为可选的初始化程序(init?)或抛出初始化程序,或者您需要在出错时调用fatalError()或类似的崩溃方法。你不能只是在没有初始化的情况下返回。

但我强烈建议你重新设计它。我没有看到任何理由参数应该是字符串。让调用者通过"character".character作为枚举(您已经拥有枚举),而不是传递.combat并在某个表中查找它。

请注意,在Swift 3中,枚举案例应始终以小写字母开头。

有点难以理解你的代码中发生了什么,但它看起来根本不应该是一个结构体。它看起来像一个枚举。像这样:

enum CharacterFeature {
    // Features for characters
}

enum CombatFeature {
    // Features for combat
}

enum Skill {
    // skills
}

enum Effect {
    // effects
}

enum Feature {
    case character(CharacterFeature, Effect)
    case combat(CombatFeature, Effect)
    case skill(Skill, Effect)
}

或者,你可以在这里使用一个结构,特别是如果有更多东西被所有功能共享:

struct Feature {
    enum Kind {
        case character(CharacterFeature, Effect)
        case combat(CombatFeature, Effect)
        case skill(Skill, Effect)
    }

    let kind: Kind
    let effect: Effect
}

关键是你通常应该使用显式类型,而不是字符串。如果你发现自己需要太多的选项,那么你经常会做错误的事情。

答案 1 :(得分:0)

假设featureCategoryListstruct Feature函数,则原始错误为:

  在self致电

之前使用

self.init

可能来自这条线:

case featureCategoryList()[0]: 
    ...
case featureCategoryList()[1]:
    ...
case featureCategoryList()[2]:

因为您在初始化之前隐式地调用self

修正上述错误后, 还需要修复这些错误:

  在从初始化程序

返回之前,未在所有路径上调用

self.init

查看Rob的答案,找出一些很好的选择。