Protocol is a very powerful feature of the Swift programming language. Protocols are used to define a “blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality.”
Swift Array provides different methods to add elements to an array. Here, append() adds 32 at the end of the array. Here, we are adding all elements of evenNumbers to primeNumbers . Note: We must use contentOf with append() if we want to add all elements from one array to another.
Specifically, you use the Array type to hold elements of a single type, the array's Element type. An array can store any kind of elements—from integers to strings to classes. Swift makes it easy to create arrays in your code using an array literal: simply surround a comma-separated list of values with square brackets.
Swift Array – With Elements of Different TypesIn Swift, we can define an array that can store elements of any type. These are also called Heterogenous Collections. To define an array that can store elements of any type, specify the type of array variable as [Any].
You've hit a variant of a problem with protocols in Swift for which no good solution exists yet.
See also Extending Array to check if it is sorted in Swift?, it contains suggestions on how to work around it that may be suitable for your specific problem (your question is very generic, maybe you can find a workaround using these answers).
You want to create a generic class, with a type constraint that requires the classes used with it conform to SomeProtocol
, like this:
class SomeClass<T: SomeProtocol> {
typealias ElementType = T
var protocols = [ElementType]()
func addElement(element: ElementType) {
self.protocols.append(element)
}
func removeElement(element: ElementType) {
if let index = find(self.protocols, element) {
self.protocols.removeAtIndex(index)
}
}
}
In Swift there is a special class of protocols which doesn't provide polymorphism over the types which implement it. Such protocols use Self
or associatedtype
keywords in their definitions (and Equatable
is one of them).
In some cases it's possible to use a type-erased wrapper to make your collection homomorphic. Below is an example.
// This protocol doesn't provide polymorphism over the types which implement it.
protocol X: Equatable {
var x: Int { get }
}
// We can't use such protocols as types, only as generic-constraints.
func ==<T: X>(a: T, b: T) -> Bool {
return a.x == b.x
}
// A type-erased wrapper can help overcome this limitation in some cases.
struct AnyX {
private let _x: () -> Int
var x: Int { return _x() }
init<T: X>(_ some: T) {
_x = { some.x }
}
}
// Usage Example
struct XY: X {
var x: Int
var y: Int
}
struct XZ: X {
var x: Int
var z: Int
}
let xy = XY(x: 1, y: 2)
let xz = XZ(x: 3, z: 4)
//let xs = [xy, xz] // error
let xs = [AnyX(xy), AnyX(xz)]
xs.forEach { print($0.x) } // 1 3
The limited solution that I found is to mark the protocol as a class-only protocol. This will allow you to compare objects using '===' operator. I understand this won't work for structs, etc., but it was good enough in my case.
protocol SomeProtocol: class {
func bla()
}
class SomeClass {
var protocols = [SomeProtocol]()
func addElement(element: SomeProtocol) {
self.protocols.append(element)
}
func removeElement(element: SomeProtocol) {
for i in 0...protocols.count {
if protocols[i] === element {
protocols.removeAtIndex(i)
return
}
}
}
}
The solution is pretty simple:
protocol SomeProtocol {
func bla()
}
class SomeClass {
init() {}
var protocols = [SomeProtocol]()
func addElement<T: SomeProtocol where T: Equatable>(element: T) {
protocols.append(element)
}
func removeElement<T: SomeProtocol where T: Equatable>(element: T) {
protocols = protocols.filter {
if let e = $0 as? T where e == element {
return false
}
return true
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With