非常に率直に言うと、拡張機能の作成と使用法を学ぶのはまったく新しいです。
カテゴリ全体(Swift 3.0)の拡張)を作成したかったので、アプリケーション全体でArrayに対して繰り返し操作を実行できます。 。
これは私が調査をしている間に見、理解したことであり、別の拡張を作成するために必要なデータ型に基づくのではなく、一般的なはずのさまざまな方法で拡張を作成したかったのです。
上記の例では、特定のデータ型ごとの拡張を行う場合、単一の拡張を作成する必要があります。一般的なカテゴリ(Extension in Swift)を作成する方法がある場合は、ガイダンスが必要でした。
extension _ArrayType where Generator.Element == Int
extension Array where Element: Equatable
extension Array where Element == Int
extension _ArrayType where Generator.Element == Float
extension SequenceType where Self.Generator.Element: FloatingPointType
extension Array where Element: DoubleValue
extension Sequence where Iterator.Element == String
、等...
注:つまり、に基づいてアクションを実行したいと考えることができます上記の要件に従って、各データ型の単一の拡張を作成するのではなく、単一の拡張のArray。
コメントで述べたように、これを達成する1つの方法は、カバーしたい型が採用する独自のプロトコルを作成することです(コメントではContent
と呼ばれ、この例では以下で使用されます)(from 最初のソース ):
protocol Content {
var hash: String { get }
}
extension Array where Element : Content {
func filterWithId(id : String) -> [Element] {
return self.filter { (item) -> Bool in
return item.id == id
}
}
}
しかし、元の質問は主に配列の一般的な拡張について尋ねているようですが、1つのコメントでは不可能であるとしていますが、Swiftで100%可能です(これは大きなSwift機能、実際には( second source から)。
たとえば、Int
sのみに特定の拡張メソッドを定義する場合は、次のようにできます。
extension Sequence where Iterator.Element == Int {
var sum: Int {
return reduce(0, +)
}
}
質問の元の要件は、データ型にとらわれない可能性がある拡張メソッドであるため、共通に保つ必要があるようです。私が正しく理解していれば、これらのデータ型は一般にEquatable
やHashable
にある程度準拠しているようです。これは、この種のジェネリックスタッフが機能するための最小要件です。ただし、この要素の適合性により、次のことが可能になります。
extension Sequence where Iterator.Element is Equatable {
func extensionMethodName<T: Equatable>(_ input: [T], singleElement: T) -> [T] {
// T is now a generic array of equatable items. You can implement whatever extension logic you need with these.
// I added different ways of passing in and returning this generic type, but the only thing that is likely going to be consistent is the `<T: Equatable>` which is Swift standard syntax for declaring generic type parameters for a method.
}
}
Swift構文はすばやく変更され、ここにあるものはすぐに古くなる可能性がありますが、 このガイド はAppleおよび^の上で使用されるGenerics
の最新の構文を示します。
私の答えは、上記の例/構文で使用されているいくつかのStackOverflow
の質問/回答から引用しています。ソース: (SO Source)(SO Source 2)
要約すると、すべてのArray
型の一般的な関数/変数の両方を持ち、型固有の拡張のオーバーライドがまだある完全にカスタムの拡張ソリューションでは、上記のすべてのメソッドを組み合わせることができます。
Where句では、「エレメントタイプにこれらのルールがある場合、この拡張を検討する」を指定します。
すべての拡張機能ですべてのメソッドを実装する必要はありません。
例えば:
_Array<Element>
_を拡張して、通常はメソッドfoo(_:Element)
を使用する場合:
_extension Array {
func foo(bar: Element) { /*your code goes here */ }
}
_
ElementがEquatable
(Int
、Double
および...またはEquatable
としてマークした構造体/クラスを含む)を実装した_Array<Element>
_を拡張したい場合:
_extension Array where Element: Equatable {
func find(value: Element) -> Bool {
return index(of: value) != nil
}
}
_
Sequence
がElement
である場合にNumeric
を拡張し、get専用の変数sumを使用する場合:
_extension Sequence where Element: Numeric {
var sum: Element {
return reduce(0, +)
}
}
_
_Collection<Collection<Element: Equatable>>
_を拡張して、2Dコレクションと比較するメソッドを用意します。
_extension Collection
where Iterator.Element: Collection,
Iterator.Element.Iterator.Element: Equatable {
func compare(to: Self) -> Bool {
let flattenSelf = self.reduce([], +)
let flattenTo = to.reduce([], +)
return flattenSelf.count == flattenTo.count &&
Zip(flattenSelf, flattenTo).reduce(true) { $0 && $1.0 == $1.1 }
}
}
_
sort
、find
などのメソッドを使用するために配列またはコレクションを拡張する必要はありません。これらのメソッドのほとんどは、_Element: Equatable
_または_Element: Comparable
_の場合、コンパイラー内ですでに拡張されています。 map
、filter
、reduce
を使用すると、コードをあまり必要とせずに、より複雑な構造を実現できます。