简体   繁体   English

init中的Swift通用约束

[英]Swift Generic constraints in init

I have generic and I want to be able to initialize it with specific constrains. 我有泛型,我希望能够使用特定的约束来初始化它。 The constraints are only there for initialization. 约束仅用于初始化。 The rest of the class doesn't care. 班上的其他人都不在乎。 Here is a simplified example: 这是一个简化的例子:

struct Generic<T> {
  let compare: (T, T) -> Bool
  init<T: Equatable>(data: [T]) {
    let handler: (T, T) -> Bool = { $0 == $1 }
    compare = handler
    insert(data)
  }

  init(compareHandler: (T, T) -> Bool, data[T]) {
    compare = self.compareHandler
    insert(data)
  }
}

You can see there's two initializers. 你可以看到有两个初始化器。 The second one obviously works fine. 第二个显然工作正常。 However, in the first one the local type T is mismatched with the struct's generic Type. 但是,在第一个中,本地类型T与结构的泛型类型不匹配。 So, for example, attempting to insert data I get Cannot invoke 'insert' with an argument list of type '([T])' . 因此,例如,尝试插入我得到的数据Cannot invoke 'insert' with an argument list of type '([T])' Is it possible for me to specialize the Struct's generic type only for the initialization or a specific function? 我是否可以仅针对初始化或特定函数专门化Struct的泛型类型?

Note, I've already tried init<T where T:Equatable>(data: [T]) to the same effect. 注意,我已经尝试过init<T where T:Equatable>(data: [T])效果相同。

Update 更新

I'm using the following workaround: I create a top level function and removing the specialized init: 我正在使用以下解决方法:我创建一个顶级函数并删除专用的init:

func equatableHandler<T: Equatable>(left: T, right: T) -> Bool {
  return left == right
}

Clients of the struct can initialize using: Generic(compareHandler: equatableHandler, data: data) struct的客户端可以使用: Generic(compareHandler: equatableHandler, data: data)进行初始化

It's not quite the "convenience" of using a specialized init , but I suppose it works well enough for my purposes. 它不是使用专用init的“便利”,但我认为它对我的目的来说足够好。 I'm not a fan of creating top-level functions, but the generic is used so often for "Equatable" generics that it makes sense for me to define the handler once for clients to use. 我不是创建顶级函数的粉丝,但泛型经常用于“Equatable”泛型,因此我为客户端定义一次处理程序是有意义的。

The problem is that the first init method 问题是第一个init方法

init<T: Equatable>(data: [T]) 

introduces a local type placeholder T which hides (and is completely unrelated to) the placeholder T of the Generic type, so it is essentially the same problem as in Array extension to remove object by value . 引入了一个本地类型的占位符T ,它隐藏(并且完全不相关) Generic类型的占位符T ,因此它与Array扩展中的问题基本上是相同的问题。

As of Swift 2 you can solve that with a "restricted extension": 从Swift 2开始,你可以通过“限制扩展”来解决这个问题:

extension Generic where T : Equatable {
    init(data: [T]) {
        let handler: (T, T) -> Bool = { $0 == $1 }
        compare = handler
        // ...
    }
}

For Swift 1.x the only solution is probably to define a global helper function 对于Swift 1.x,唯一的解决方案可能是定义全局辅助函数

func makeGeneric<T : Equatable>(data: [T]) -> Generic<T> {
    return Generic(compareHandler:  { $0 == $1 }, data: data)
}

(and I could not think of a sensible name for the function :). (我无法想到这个功能的合理名称:)。

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

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