Extending typed array by conforming to a protocol in Swift 2
You can't apply a lot of logic to conformance. It either does or does not conform. You can however apply a little bit of logic to extensions. The code below makes it easy to set specific implementations of conformance. Which is the important part.
This is used as a typed constraint later.
class SomeType { }
This is your protocol
protocol SomeProtocol {
func foo()
}
This is an extension of the protocol. The implementation of foo()
in an extension of SomeProtocol
creates a default.
extension SomeProtocol {
func foo() {
print("general")
}
}
Now Array
conforms to SomeProtocol
using the default implementation of foo()
. All arrays will now have foo()
as a method, which is not super elegant. But it doesn't do anything, so it's not hurting anyone.
extension Array : SomeProtocol {}
Now the cool stuff:
If we create an extension to Array
with a type constraint for Element
we can override the default implementation of foo()
extension Array where Element : SomeType {
func foo() {
print("specific")
}
}
Tests:
let arrayOfInt = [1,2,3]
arrayOfInt.foo() // prints "general"
let arrayOfSome = [SomeType()]
arrayOfSome.foo() // prints "specific"
How can I extend typed Arrays in Swift?
For extending typed arrays with classes, the below works for me (Swift 2.2). For example, sorting a typed array:
class HighScoreEntry {
let score:Int
}
extension Array where Element == HighScoreEntry {
func sort() -> [HighScoreEntry] {
return sort { $0.score < $1.score }
}
}
Trying to do this with a struct or typealias will give an error:
Type 'Element' constrained to a non-protocol type 'HighScoreEntry'
Update:
To extend typed arrays with non-classes use the following approach:
typealias HighScoreEntry = (Int)
extension SequenceType where Generator.Element == HighScoreEntry {
func sort() -> [HighScoreEntry] {
return sort { $0 < $1 }
}
}
In Swift 3 some types have been renamed:
extension Sequence where Iterator.Element == HighScoreEntry
{
// ...
}
Extension of array with Elements conforming a protocol in swift 2.0
Ok, looks like it is a well known behavior... for someone is a bug.
Actually, no, this is just a known limitation of the compiler. Unfortunately, today, the protocol type (or "existential" as we compiler weenies call it) doesn't conform to the protocol:
protocol P {}
func g<T: P>(_: T) {}
struct X : P {}
struct Y<T: P> {}
Y<P>() // error: type 'P' does not conform to protocol 'P'
source: https://forums.developer.apple.com/message/15955#15955
Extend Array to conform to protocol if Element conforms to given protocol
Swift 4.2
In Swift 4.2 I was able to extend an array with the elements conforming to a protocol like this:
public extension Array where Element: CustomStringConvertible{
public var customDescription: String{
var description = ""
for element in self{
description += element.description + "\n"
}
return description
}
}
How do I create an extension to allow an array of a custom type to conform to a protocol?
Short answer: no.
You can constrain an extension, but a constrained extension can't contain an inheritance clause (the Swift proposal @Code Different linked above is exactly what you're looking for).
One workaround would be to make the constrained extension, but just add your own property, rather than having it conform to CustomStringConvertible
.
class Banana : CustomStringConvertible {
var description: String {
return "a banana"
}
}
let aBanana = Banana()
aBanana.description // "a banana"
extension Array where Element: Banana {
var bananaDescription: String {
return "a bunch of bananas"
}
}
let bananas = [Banana(), Banana(), Banana()]
bananas.bananaDescription // "a bunch of bananas"
Worth noting, too, that Array
already conforms to CustomStringConvertible
.
let bananas = [Banana(), Banana(), Banana()]
bananas.description // "[a banana, a banana, a banana]"
Heterogeneous array that conforms to protocol with associated type in Swift
See if this fits your needs.
Approach:
Remove the associated type
Implementation:
protocol BProtocol {
func aFunc(parameter: BProtocol) -> Bool
}
extension String : BProtocol {
func aFunc(parameter: BProtocol) -> Bool {
return true
}
}
extension Int : BProtocol {
func aFunc(parameter: BProtocol) -> Bool {
return false
}
}
extension Array : BProtocol where Element == BProtocol {
func aFunc(parameter: BProtocol) -> Bool {
return self.reduce(true, { r,e in r || e.aFunc(parameter: parameter) })
}
}
Invoking:
let a1 : [BProtocol] = [1, 2, 3, "Hi"]
let boolean = a1.aFunc(parameter: 1)
Related Topics
Swift Programmatically Create Function for Button with a Closure
Accessing Global Variable in Swift
Understanding Singleton in Swift
Cast to Different C Struct Unsafe Pointer in Swift
How to Masking the Last Number in Swift
Getting Twitter Profile Image with Parse in Swift
How to Specify the Type Information of an Array That Would Hold Swiftui Custom Views
Self' Is Only Available in a Protocol or as the Result of a Class Method
Swift 3 - How to Write Functions with No Initialisers Like the New Uicolors
Inferred to Have Type 'Anyclass', Which May Be Unexpected
How to Stop a Dispatchqueue in Swift
Referencing Self in Super.Init
Hittest Prints Ar Entity Name Even When I am Not Tapping on It
Swift For-In Loop with Enumerate on Custom Array2D Class
Way to Purge All But One Object Types (Models) in a Realm