如何创建一个受限于结构的泛型类?

时间:2016-02-26 15:35:01

标签: swift

由于Swift Language Guide指出泛型类型可以约束类或协议,如下所示:

public class MyGenericClass<T:Equatable> {
    func printEquality(a:T, b:T) {
        if a == b {
            print("equal")
        } else {
            print("not equal")
        }
    }
}

我可以某种方式将T限制为struct吗?

我的用例是值类型的观察者类,只能由结构使用。

作为旁注:我知道有例如仅类协议,只能由类实现。这并不是真正相关,但表明有时会有一种特殊的方式来达到目标​​。

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

2 个答案:

答案 0 :(得分:2)

你不能(从Swift 2.2开始)。

根本不可能。 struct版本没有AnyObject,即AnyValue协议(自动为所有值类型实施)。

我自己也遇到过这个问题,我很遗憾地说除了严格遵守非正式协议之外别无他法。希望Swift 3能够解决这个问题。

答案 1 :(得分:1)

另一个答案很好地回答了这个问题(即:你不能(但是?))。

我想我会补充一点,你可以使用运行时内省和可用的初始化器来模拟至少这种行为;这样,只有当T是一个结构(符合Equatable)时,通用类的初始化才会成功。

public class MyGenericClass<T: Equatable> {
    var foo: T

    init?(bar: T) {
        foo = bar

        if Mirror(reflecting: foo).displayStyle != .Struct {
            return nil
        }
    }
}

struct Foo : Equatable {
    let foo = 1
}
func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs.foo == rhs.foo }

/* Example */
if let _ = MyGenericClass<Int>(bar: 1) {
    print("Integer")
}
if let _ = MyGenericClass<Foo>(bar: Foo()) {
    print("Foo-Struct")
}
// prints only "Foo-Struct"

您可以将失败的初始化解释为您的通用T“的不一致”仅允许T为结构“,并且可能使用可选绑定(/ .. 。)在实践中将它与观察者类一起使用。