Swift Optionals最佳做法

时间:2015-07-03 17:13:03

标签: swift class

我认为我理解Swift选项背后的想法,即具有非可选类型的属性表示必须有,而具有可选类型的属性是可能的,但在我看来它是这些功能之一,如强制性的异常处理或强制性缩进,虽然理论上有很大的意外实际后果。这就是我面临的情况。我正在创建一个医学应用程序来评估认知能力。该测试由提供者管理给患者,并且包括,例如,10个不同的活动。应用程序的数据模型是一个简单的类Test,用于收集活动的结果。每个活动都有自己的类,患者和提供者也是如此。业务逻辑规定必须完成所有活动或测试无效,并且患者和提供者显然是强制性的。类Test的自然定义是

 class Test {
    var provider: Provider
    var patient: Patient
    var activity1: Activity1
    var activity2: Activity2
    ...
    var activity10: Activity10
    }

现在问题是要创建类Test的实例,我需要获得所有活动的所有结果;在实践中,我必须继承ProviderPatient和活动的所有单个实例,并且只有在测试完成时创建Test的实例,这当然是不切实际的。因此,出于实际目的,Test的所有属性都可以是可选的,并且类是以递增方式填充的,但现在类Test并不忠实地表示数据模型;此外,必须解开对属性的任何访问。一种选择是创建一个非可选的活动数组,这些活动可以逐步增长,但是这个类不再代表数据模型的意图。最后,可以使用所有可选属性创建“姐妹类”PartialTest,并在完全填充PartialTest时创建Test的实例。仍然看起来有点矫枉过正。

那么,我是否误解了Swift中的选项角色?如果没有,是否有任何实用的方法来保持班级Test应该是什么?

1 个答案:

答案 0 :(得分:4)

您可以执行以下操作:

class Test {
    var provider: Provider
    var patient: Patient
    var activity1: Activity1! = nil
    var activity2: Activity2! = nil
    // ...
    var activity10: Activity10! = nil

    var isComplete: Bool {
        return activity1 != nil
            && activity2 != nil
            // ...
            && activity10 != nil
    }
}

...然后只有在isComplete == true时才能访问测试中的活动,我认为可以从概念上改进设计。

但一般来说,我会重新考虑设计,以避免在Test类中使用一组硬编码的活动来限制自己。 E.g:

protocol Activity {
    var isMandatory: Bool { get }
    var isComplete: Bool { get }
}

struct Activity1: Activity {
    let isMandatory: Bool

    var result1: Int! = nil

    var isComplete: Bool {
        return result1 != nil
    }

    init(isMandatory: Bool) {
        self.isMandatory = isMandatory
    }
}

class Test {
    var provider: Provider
    var patient: Patient
    var activities: [Activity] = [
        Activity1(isMandatory: true)
        // ...
    ]

    var isComplete: Bool {
        return activities.reduce(true) {
            $0 && $1.isComplete
        }
    }
}

......或某种更好的方法。