【问题标题】:Swift Generics: Extending a non-generic type with a property of generic type where the generic parameter is the extended typeSwift 泛型:使用泛型类型的属性扩展非泛型类型,其中泛型参数是扩展类型
【发布时间】:2020-05-18 13:40:57
【问题描述】:

问题

我有一种类型,它采用一个泛型参数,需要从UIView 继承:

class Handler<View: UIView> {
   ...
}

现在,我想写一个UIView extension 来提供一个返回Handler 并使用Self 作为通用参数的属性,这样在UIView 的子类中我总是会得到@987654327 类型的处理程序@:

extension UIView {
   var handler: Handler<Self>? { return nil }
}

但是这不能编译:

协变 'Self' 只能出现在属性类型的顶层

我也尝试过先定义一个协议HandlerProvider

public protocol HandlerProvider {
    associatedtype View: UIView

    var handler: Handler<View>? { get }
}

(到目前为止一切顺利),然后使用该协议扩展 UIView

extension UIView: HandlerProvider {
    public typealias View = Self

    public var handler: Handler<View>? { return nil }
}

但这也不编译:

Covariant 'Self' 只能作为属性、下标或方法结果的类型出现;你的意思是“UIView”吗?

问题

在 Swift 中有没有办法使用 Self 作为扩展属性的通用参数?

【问题讨论】:

  • 在 Swift 5 中,existentials 仅限于没有关联类型和自约束的协议。我正在研究解决方案。
  • @RedX 你能指出我在哪里可以了解有关此问题的更多信息吗?

标签: swift generics


【解决方案1】:

这是可能的方法(以不同的方向思考泛型)。

使用 Xcode 11.4 / swift 5.2 测试

// base handling protocol
protocol Handling {
    associatedtype V: UIView

    var view: V { get }
    init(_ view: V)

    func handle()
}

// extension for base class, will be called by default for any
// UIView instance that does not have explicit extension 
extension Handling where V: UIView {
    func handle() {
        print(">> base: \(self.view)")
    }
}

// extension for specific view (any more you wish)
extension Handling where V: UIImageView {
    func handle() {
        print(">> image: \(self.view)")
    }
}

// concrete implementer
class Handler<V: UIView>: Handling {
    let view: V
    required init(_ view: V) {
        self.view = view
    }
}

// testing function
func fooBar() {
    // handlers created in place of handling where type of
    // handling view is know, so corresponding handle function
    // is used
    Handler(UIView()).handle()
    Handler(UIImageView()).handle()
}

输出:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多