将类型传递给通用 Swift 扩展,或者理想情况下推断它 [英] Pass in a type to a generic Swift extension, or ideally infer it

查看:28
本文介绍了将类型传递给通用 Swift 扩展,或者理想情况下推断它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说你有

 class Fancy:UIView

您想查找所有兄弟 Fancy 视图.没问题...

you want to find all sibling Fancy views. No problem...

    for v:UIView in superview!.subviews
        {
        if let f = v as? Fancy
            { f.hungry = false }
        }

所以,尝试一个扩展,

public extension UIView
    {
    internal func fancySiblings()->([Fancy])
        {
            return (self.superview!
                .subviews
                .filter { $0 != self }
                .flatMap { $0 as? Fancy }
                )
        }
    }

太棒了,你现在可以

    for f:Fancy in self.fancySiblings()
        { f.hungry = false }

太棒了.

但是,

所以,像......

public extension UIView
    {
    internal func siblings<T>( something T )->([T])
        {
            return (self.superview!
                .subviews
                .filter { $0 != self }
                .flatMap { $0 as? T }
                )
        }

然后你可以这样称呼它......

and then you could call it something like this ...

    for f in self.siblings(Fancy)
    for p in self.siblings(Prancy)
    for b in self.siblings(UIButton)

你怎么能告诉"?要使用的类型的通用扩展,像那样??

How can you "tell" a generic extension the type to use, like that??

看来你可以向后推断",

It seems you can "infer it backwards",

public extension UIView
    {
    internal func incredible<T>()->([T])
        {
        return (self.superview!
         .subviews
         .filter { $0 != self }
         .flatMap { $0 as? T }
         )
        }


    for f:Fancy in self.incredible()

    for p:Prancy in self.incredible()

这很了不起,但反过来不行.

Which is amazing but doesn't work the other way.

你甚至可以...

    self.siblings().forEach{
        (f:Fancy) in
        d.hasRingOn = false
        }

所以我还是想知道怎么传入"类似于 for f in self.siblings(Fancy) 的类型,理想情况下,甚至还可以推断它.

So I would still like to know how to "pass in" a type something like for f in self.siblings(Fancy) and, ideally, even infer it also.

推荐答案

只需使用.Type:

internal func siblings<T>( something : T.Type)->([T]) {
    ...
}

之后 for f in self.siblings(Fancy) 应该完全按预期工作.

Afterwards for f in self.siblings(Fancy) should work exactly as expected.

完整的工作示例:

class Fancy : UIView {}

public extension UIView {
    internal func siblings<T>( _ : T.Type)->([T]) {
        return (self.superview!
            .subviews
            .filter { $0 != self }
            .flatMap { $0 as? T }
        )
    }
}

let superView = UIView()
let view = UIView()
superView.addSubview(view)
superView.addSubview(UIView())
superView.addSubview(Fancy())

print(view.siblings(Fancy))

正确输出一个Fancy视图!

解决要求添加的可选使用显式类型参数或使编译器的类型推断生效.你可以在同一个扩展中创建第二个方法

To address the requested addition for optionally using the explicit type parameter or take effect of the type inference of the compiler. You can create a second method in the same extension

internal func siblings<T>()->([T]) {
    return siblings(T)
}

这种提供显式类型参数调用方法一的方式,省略它会要求您使其可推断,并将调用第二个函数,在内部调用第一个函数.

That way providing a explicit type parameter calls method one, omitting it will require you to make it inferable and will call the second function which in terms calls the first one internally.

或者,你可以使用更swifty的方式,使显式类型参数成为可选的,默认nil.值得注意的是,这将在省略类型参数的情况下强制进行推断:

Or, you can use the far more swifty way and make the explicit type argument an optional with default nil. That, remarkably, will force the inference in case of omitting the type argument:

// power extension, it provides both infered or stated typing
internal func siblings<T>(_ : T.Type? = nil) -> ([T]) {
    return (self.superview!
        .subviews
        .filter { $0 != self }
        .flatMap { $0 as? T }
        )
}

这将使您能够通过

for f in self.siblings(Fancy)

甚至

for f : Fancy in self.siblings()

两者都可以工作,但仍然只定义一个函数.

Both will work while still only defining one function.

这篇关于将类型传递给通用 Swift 扩展,或者理想情况下推断它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆