我可以将通用参数约束为* not *是可选的吗?

时间:2015-12-15 21:09:37

标签: swift generics

假设我有这段代码:

for (int i = 0, j = 0; i < records.Length; i++, j++)
{
    customRecord = (CustomRecord)records[i];

    var myNetSuiteObject = MyNetSuiteObject.FromCustomSearchRecord(customRecord);
}

我可以编写一个func hello<T>(thing: T) -> String { return "hello \(thing)" } 函数的版本,如果它被传递给了一个可选项,它将无法编译吗?

hello

我想也许它可以通过T上的协议一致性或let foo = "some" let bar: String? = nil print(helloNoOptional(foo)) // should compile print(helloNoOptional(bar)) // should not compile 条款来实现,但我想不出它究竟会如何运作。

我想要这样做的原因是因为我正在处理遗留代码库中的实际函数,如果where为零,则该函数没有明显的行为。因此,我宁愿阻止thing在可选项上调用,而不是在hello中解包hello并尝试找出合理的错误行为。

更新:

可能的路径......我意识到Optional枚举符合thing协议。因此,如果我能找到一种方法将我的泛型约束为符合类型,我可以事实上排除选项。但我不知道是否有可能做类似

的事情
NilLiteralConvertible

2 个答案:

答案 0 :(得分:6)

我能想到的最好是超载并在运行时检查:

func hello<T>(thing: T) -> String {
    return "hello \(thing)"
}

fun hello<T>(thing: T?) -> String {
    fatalError("No optionals allowed!")
}

hello("swift")  // fine
hello(2)        // fine
hello(Int("2")) // fatal error

但我不知道如何产生编译时错误。

答案 1 :(得分:1)

已修改

您可以创建一个虚拟协议(下面为NotOfOptionalType),并通过此协议扩展您希望在通用函数中使用的所有类型。最后使用伪协议作为泛型函数中参数的类型约束; optionals不符合此类型约束,如果将它们作为这些函数的参数发送,则在编译时会给出错误。

// dummy protocol
protocol NotOfOptionalType {}

extension String : NotOfOptionalType {}
extension Int : NotOfOptionalType {}
extension Double : NotOfOptionalType {}
// ... extend to the types you will use

func hello<T: NotOfOptionalType > (thing: T) -> String {
    return "hello \(thing)"
}

let foo = "some"
var bar: String? = nil

print(hello(foo))  // compiles
print(hello(bar))  // fails at compile time
bar = "something"
print(hello(bar))  // fails at compile time
print(hello(bar!)) // compiles