简体   繁体   English

Swift:使用不同的自定义类型创建数组

[英]Swift: Create array with different custom types

I'm making a registration form app. 我正在制作注册表应用程序。 This lets users create questions and display the created questions in a UITableView. 这使用户可以创建问题并在UITableView中显示创建的问题。 Users can create 2 types of questions, text input(using textfields) and multiple choice(using segmentedcontrol). 用户可以创建两种类型的问题,文本输入(使用文本字段)和多项选择(使用segmentedcontrol)。 Here is the class I created to make this happen. 这是我为实现此目的而创建的类。

class Question {
var Label: String
var required: Int

// create question
init (Label: String, required: Int) {
    self.Label = Label
    self.required = required

    if (self.required == 0) {
        self.Label = self.Label + " *"
    }
}
}

class textInput: Question {
var placeHolder: String

init (placeHolder: String, Label: String, required: Int) {
    self.placeHolder = placeHolder
    super.init(Label: Label, required: required)
}
}

class multiChoice: Question {
var answers: [String]

init(answers: [String], Label: String, required: Int) {
    self.answers = answers
    super.init(Label: Label, required: required)
}
}

I will need to populate an array with textInput or multiChoice types which will be displayed in the UITableView. 我需要用textInput或multiChoice类型填充数组,这些类型将显示在UITableView中。 In C++ you can use templates to accomplish this arbitrary type issue. 在C ++中,您可以使用模板来完成此任意类型的问题。 Is there a way to do that in Swift, and if so could I get pointers on how to do it with these classes? 在Swift中有没有办法做到这一点,如果可以,我可以得到关于如何使用这些类的指针吗?

First off. 首先。 Change your Question class as follows: 如下更改您的Question类:

var required: Bool

init (Label: String, required: Bool) {
    self.Label = Label
    self.required = required

    if self.required {
        self.Label = self.Label + " *"
    }
}

Next, you can use an array of type [Question] to achieve what you're looking for. 接下来,您可以使用[Question]类型的数组来实现所需的内容。 Then you can do specific actions based on the class using guard or if let structures. 然后,您可以使用guardif let结构基于类执行特定操作。

One way to accomplish what you want that is very clean and type safe is to create an enum with associated values for the different types that you will be using. 实现您想要的非常干净且类型安全的方法之一是创建一个enum ,该enum具有将要使用的不同类型的关联值。 Then you can create an array of enum values and unwrap them using a switch to get at what you want. 然后,您可以创建一个enum值数组,并使用switch将其解包以获取所需的内容。

class QuestionBase {
    var label: String
    var required: Bool

    // create question
    init (label: String, required: Bool) {
        self.label = label
        self.required = required

        if required {
            self.label = self.label + " *"
        }
    }
}

class TextInputQuestion: QuestionBase {
    var placeHolder: String

    init (placeHolder: String, label: String, required: Bool) {
        self.placeHolder = placeHolder
        super.init(label: label, required: required)
    }
}

class MultiChoiceQuestion: QuestionBase {
    var answers: [String]

    init(answers: [String], label: String, required: Bool) {
        self.answers = answers
        super.init(label: label, required: required)
    }
}

enum Question {
    case TextInput(TextInputQuestion)
    case MultiChoice(MultiChoiceQuestion)
}

let q1 = TextInputQuestion(placeHolder: "placeholder", label: "q1", required: true)
let q2 = MultiChoiceQuestion(answers: ["answer1", "answer2"], label: "q2", required: false)

let questions: [Question] = [.TextInput(q1), .MultiChoice(q2)]

for question in questions {
    switch question {
    case .TextInput(let question):
        print(question.placeHolder)
    case .MultiChoice(let question):
        print(question.answers)
    }
}

enum s are very powerful this way. enum通过这种方式非常强大。 The array is all of one type: Question . 数组是一种类型: Question The associated values can be of any type. 关联的值可以是任何类型。 You could have a TrueFalse case , or even an Essay case . 您可能有TrueFalse case ,甚至有Essay case

I rewrote much of your code - it violated a lot of the Swift style guidelines and it made it very hard to read. 我重写了许多您的代码-它违反了许多Swift风格指南,因此很难阅读。 Type names, like class names, should all be LikeThis (starting with an uppercase letter), while properties should all be in camelCase (starting with a lowercase letter). 类型名称(如class名称)应全部为LikeThis (以大写字母开头),而属性均应为camelCase (以小写字母开头)。 And I renamed some of the types just to make it more clear what the intentions were. 我重命名了某些类型,只是为了更清楚地说明意图是什么。 You can take those changes or leave them. 您可以进行更改或保留更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM