通过遵守Swift 2中的协议扩展类型化数组

通过遵守Swift 2中的协议扩展类型化数组,swift,generics,swift2,swift-extensions,Swift,Generics,Swift2,Swift Extensions,我想扩展一个类型化数组array,使其符合协议SomeProtocol。现在我知道您可以像下面这样扩展类型化数组: extension Array where Element: SomeType { ... } 您还可以扩展对象以符合协议,如下所示: extension Array: SomeProtocol { ... } 但我不知道什么是使类型化数组符合协议的正确语法,例如: extension (Array where Element: SomeType): SomeProtocol

我想扩展一个类型化数组
array
,使其符合协议
SomeProtocol
。现在我知道您可以像下面这样扩展类型化数组:

extension Array where Element: SomeType { ... }
您还可以扩展对象以符合协议,如下所示:

extension Array: SomeProtocol { ...  }
但我不知道什么是使类型化数组符合协议的正确语法,例如:

extension (Array where Element: SomeType): SomeProtocol { ... }

任何Swift 2专家都知道如何做到这一点?

您不能对一致性应用大量逻辑。它要么符合,要么不符合。不过,您可以对扩展应用一点逻辑。下面的代码可以轻松设置一致性的特定实现。这是最重要的部分

这将在以后用作类型化约束

class SomeType { }
这是你的协议

protocol SomeProtocol {

    func foo()

}
这是协议的扩展。在
SomeProtocol
的扩展中实现
foo()
,会创建一个默认值

extension SomeProtocol {

    func foo() {
        print("general")
    }
}
现在
Array
使用
foo()的默认实现符合
SomeProtocol
。所有数组现在都将使用
foo()
作为一种方法,这并不是非常优雅的。但它什么也没做,所以它不会伤害任何人

extension Array : SomeProtocol {}
现在最酷的东西是: 如果我们为
元素
创建一个带有类型约束的
数组
扩展,我们可以覆盖
foo()的默认实现

测试:

let arrayOfInt = [1,2,3]
arrayOfInt.foo() // prints "general"

let arrayOfSome = [SomeType()]
arrayOfSome.foo() // prints "specific"

我自己也在这方面做了一些尝试,有一些方法可以模仿你正在寻找的行为


方法#1

定义一个协议
SomeType
,作为
SomeProtocol
Array
扩展所涵盖类型的类型约束;其中后者包含一些您希望扩展
Array
的简洁方法的蓝图

protocol SomeType {
    var intValue: Int { get }
    init(_ value: Int)
    func *(lhs: Self, rhs: Self) -> Self
    func +=(inout lhs: Self, rhs: Self)
}

extension Int : SomeType { var intValue: Int { return self } }
extension Double : SomeType { var intValue: Int { return Int(self) } }
    /* Let's not extend 'Float' for now
extension Float : MyTypes { var intValue: Int { return Int(self) } } */

protocol SomeProtocol {
    func foo<T: SomeType>(a: [T]) -> Int?
}
现在,我们使用协议
SomeProtocol
中打印的
foo(…)
函数扩展了
Array
元素
SomeType

/* Tests */
let arr1d : [Double] = [1.0, 2.0, 3.0]
let arr2d : [Double] = [-3.0, -2.0, 1.0]

let arr1f : [Float] = [1.0, 2.0, 3.0]
let arr2f : [Float] = [-3.0, -2.0, 1.0]

func bar<U: SomeType> (arr1: [U], _ arr2: [U]) -> Int? {
    return arr1.foo(arr2)
}
let myInt1d = bar(arr1d, arr2d) // -4, OK

let myInt1f = bar(arr1f, arr2f)
    /* Compile time error: "Cannot convert value of type '[Float]'
       to expected argument type '[_]'"                            */
使用结构将
GenericProtocol
转发到
AbstractType
(此处符合
SequenceType
),并在后者中实现协议蓝图:

struct SomeArrayProtocol<T: SequenceType> : GenericProtocol {
    private let _repeatNumberNumberManyTimes : (Int) -> T
    private let _removeRandomElement : (T) -> T
    private let _countNumberOf42s : (T) -> Int

    init<P : GenericProtocol where P.AbstractType == T>(_ dep : P) {
        _repeatNumberNumberManyTimes = dep.repeatNumberNumberManyTimes
        _removeRandomElement = dep.removeRandomElement
        _countNumberOf42s = dep.countNumberOf42s
    }

    func repeatNumberNumberManyTimes(arg: Int) -> T {
        return _repeatNumberNumberManyTimes(arg)
    }

    func removeRandomElement(arg: T) -> T {
        return _removeRandomElement(arg)
    }

    func countNumberOf42s(arg: T) -> Int {
        return _countNumberOf42s(arg)
    }
}
最后,一些测试:

let myGenericExtensionUsedForDouble : SomeArrayProtocol<Array<Double>> = SomeArrayProtocol(SomeArrayGenericExtensions())
let myGenericExtensionUsedForFloat : SomeArrayProtocol<Array<Float>> = SomeArrayProtocol(SomeArrayGenericExtensions())
// let myGenericExtensionUsedForInt : SomeArrayProtocol<Array<Int>> = SomeArrayProtocol(SomeArrayGenericExtensions()) // Error! Int not SomeType, OK!

var myDoubleArr = [10.1, 42, 15.8, 42.0, 88.3]
let my10EntriesOfTenDoubleArr = myGenericExtensionUsedForDouble.repeatNumberNumberManyTimes(10) // ten 10:s
let myFloatArr : Array<Float> = [1.3, 5, 8.8, 13.0, 28, 42.0, 42.002]
let myIntArr = [1, 2, 3]

let a = myGenericExtensionUsedForDouble.countNumberOf42s(myDoubleArr) // 2
let b = myGenericExtensionUsedForFloat.countNumberOf42s(myFloatArr) // 1

myDoubleArr = myGenericExtensionUsedForDouble.removeRandomElement(myDoubleArr) // [10.1, 15.8, 42.0, 88.3]
让MyGenericeExtensionsUsedForouble:SomeArrayProtocol=SomeArrayProtocol(SomeArrayGenericeExtensions())
让MyGenericeExtensions用于float:SomeArrayProtocol=SomeArrayProtocol(SomeArrayGenericeExtensions())
//让myGenericExtensionUsedForInt:SomeArrayProtocol=SomeArrayProtocol(SomeArrayGenericExtensions())//错误!Int不是什么类型的,好吧!
var myDoubleArr=[10.1,42,15.8,42.0,88.3]
让my10entriesoftendoubler=myGenericExtensionUsedForDouble.repeatNumberNumberManyTimes(10)//ten 10:s
让myFloatArr:Array=[1.3,5,8.8,13.0,28,42.0,42.002]
设myIntArr=[1,2,3]
设a=myGenericExtensionUsedForDouble.countNumberOf42s(myDoubleArr)//2
设b=myGenericExtensionUsedForFloat.countNumberOf42s(myFloatArr)//1
myDoubleArr=myGenericExtensionUsedForDouble.RemoveAndOmeElement(myDoubleArr)/[10.1,15.8,42.0,88.3]


我有点不确定上面的方法2是否真的对数组有一些实际应用(在米兰的报道中,他处理非序列类型,也许更有用);这是一项相当大的工作,没有那么多额外的费用。然而,这可能是一个很有启发性、很有娱乐性的练习:)

在较新版本的Swift中,可以写:

扩展数组:SomeProtocol,其中元素==SomeType{…}

不确定这是在哪个版本的Swift中实现的,但以下内容适用于Swift 4.1

class SomeType { }

protocol SomeProtocol {
    func foo()
}

extension Array: SomeProtocol where Element == SomeType {
    func foo() {
        print("foo")
    }
}

let arrayOfSome = [SomeType()]
arrayOfSome.foo() // prints "foo"

let arrayOfInt = [1,2,3]
arrayOfInt.foo() // Will not compile: '[Int]' is not convertible to 'Array<SomeType>'
class SomeType{}
协议{
func foo()
}
扩展数组:SomeProtocol,其中元素==SomeType{
func foo(){
打印(“foo”)
}
}
让arrayOfSome=[SomeType()]
arrayOfSome.foo()//打印“foo”
设ArrayFint=[1,2,3]
arrayOfInt.foo()//不会编译:“[Int]”不能转换为“Array”

(我知道这个问题特别要求使用Swift 2,但我添加它是为了参考)

看看这个答案中的StringType协议来扩展字符串数组带有约束的“array”类型的扩展不能有继承子句。没有逻辑。你能给我们提供一些有用的例子吗?@JamesHu你有时间看一下下面的答案并给出反馈吗?我查了一下,根据这个链接,它被称为Swift,并且是自4.2版以来的Swift的一部分。
struct SomeArrayProtocol<T: SequenceType> : GenericProtocol {
    private let _repeatNumberNumberManyTimes : (Int) -> T
    private let _removeRandomElement : (T) -> T
    private let _countNumberOf42s : (T) -> Int

    init<P : GenericProtocol where P.AbstractType == T>(_ dep : P) {
        _repeatNumberNumberManyTimes = dep.repeatNumberNumberManyTimes
        _removeRandomElement = dep.removeRandomElement
        _countNumberOf42s = dep.countNumberOf42s
    }

    func repeatNumberNumberManyTimes(arg: Int) -> T {
        return _repeatNumberNumberManyTimes(arg)
    }

    func removeRandomElement(arg: T) -> T {
        return _removeRandomElement(arg)
    }

    func countNumberOf42s(arg: T) -> Int {
        return _countNumberOf42s(arg)
    }
}
struct SomeArrayGenericExtensions<T: SomeType> : GenericProtocol {
    typealias AbstractType = Array<T>
    func repeatNumberNumberManyTimes(arg: Int) -> [T] {
        return Array<T>(count: arg, repeatedValue: T(arg))
    }
    func removeRandomElement(arg: [T]) -> [T] {
        var output = [T]()
        let randElemRemoved = Int(arc4random_uniform(UInt32(arg.count-1)))
        for (i,element) in arg.enumerate() {
            if i != randElemRemoved {
                output.append(element)
            }
        }
        return output
    }
    func countNumberOf42s(arg: [T]) -> Int {
        var output = 0
        for element in arg {
            if element == T(42) {
                output++
            }
        }
        return output
    }
}
let myGenericExtensionUsedForDouble : SomeArrayProtocol<Array<Double>> = SomeArrayProtocol(SomeArrayGenericExtensions())
let myGenericExtensionUsedForFloat : SomeArrayProtocol<Array<Float>> = SomeArrayProtocol(SomeArrayGenericExtensions())
// let myGenericExtensionUsedForInt : SomeArrayProtocol<Array<Int>> = SomeArrayProtocol(SomeArrayGenericExtensions()) // Error! Int not SomeType, OK!

var myDoubleArr = [10.1, 42, 15.8, 42.0, 88.3]
let my10EntriesOfTenDoubleArr = myGenericExtensionUsedForDouble.repeatNumberNumberManyTimes(10) // ten 10:s
let myFloatArr : Array<Float> = [1.3, 5, 8.8, 13.0, 28, 42.0, 42.002]
let myIntArr = [1, 2, 3]

let a = myGenericExtensionUsedForDouble.countNumberOf42s(myDoubleArr) // 2
let b = myGenericExtensionUsedForFloat.countNumberOf42s(myFloatArr) // 1

myDoubleArr = myGenericExtensionUsedForDouble.removeRandomElement(myDoubleArr) // [10.1, 15.8, 42.0, 88.3]
class SomeType { }

protocol SomeProtocol {
    func foo()
}

extension Array: SomeProtocol where Element == SomeType {
    func foo() {
        print("foo")
    }
}

let arrayOfSome = [SomeType()]
arrayOfSome.foo() // prints "foo"

let arrayOfInt = [1,2,3]
arrayOfInt.foo() // Will not compile: '[Int]' is not convertible to 'Array<SomeType>'