Reputation: 26476
Let's say that certain items can appear in a Feed
, so long as they implement the necessary properties defined by the Feedable
protocol. Let's also say that the Photo
object is feed-worthy:
extension Photo: Feedable { }
Is it possible to say that an Array
of these photos might also be Feedable
?
extension [Photo] : Feedable
Or do I always need some kind of wrapper object, such as a PhotoAlbum
, to conform to Feedable
?
Edit
To re-iterate, I was curious whether I can make only arrays of Photo
objects Feedable
. Not making Array
of any content type Feedable
, not making an array of Feedable
s itself Feedable
(both of which are offered as solutions below if that's what you need).
In other words, a solution (which I doubt exists) would allow me to define a variable of type Feedable
with the following outcomes:
var feedable: Feedable
//photo is feedable, so this is fine
feedable = Photo() //ok
//arrays of photos are feedable
let photo1 = Photo()
let photo2 = Photo()
feedable = [photo1, photo2]
//arrays of other things are not
feedable = ["no", "dice"] //nope
//even if the contents of an array are themselves Feedable, that's not sufficient. E.g. Video is Feedable, but Array of Videos is not.
let video1 = Video()
let video2 = Video()
feeble = video1 //fine
feedable = [video1, video2] //nope
Perhaps this gist (which doesn't compile of course) shows the intention more clearly.
Upvotes: 17
Views: 5294
Reputation: 6370
Answers here are almost there for what you want to do. Specifically this one, with just 1 change it can be restricted to elements of a type
as opposed to elements confirming to a protocol
.
extension Array: Feedable where Element == Photo {
}
With this extension the code posted on the question shows errors where expected and it ok everywhere else.
Upvotes: 0
Reputation: 1
You can make an array to conform a protocol like this:
typealias PhotoArray = [Photo]
extension PhotoArray: Feedable {}
Upvotes: 0
Reputation: 9354
You can achieve your goal in this way:
Swift 4:
protocol Feedable {
func foo()
}
extension String: Feedable {
func foo() {
}
}
extension Array: Feedable where Element: Feedable {
func foo() {
}
}
// or in more generic way to support Array, Set and other collection types
extension Collection: Feedable where Element: Feedable {
func foo() {
}
}
Upvotes: 13
Reputation: 2395
I didn't try in playground but maybe you can simply make an Array of Feedable:
var myPhotosArray = [Feedable]()
Then everything implementing the Feedable protocol would be allowed in the Array. If you want only a photo array, You can still subclass your Photo object to make a FeedablePhoto object.
Try this in Playground instead of downvoting without even testing. Seriously 3 downvotes without any reasons and explanations...
import UIKit
protocol Tree: class {
func grow()
}
class BigTree: Tree {
internal func grow() {
print("Big tree growing")
}
}
class SmallTree: Tree {
internal func grow() {
print("Small tree growing")
}
}
class Car {
//not a tree
}
var manyTrees = [Tree]()
manyTrees.append(BigTree())
manyTrees.append(SmallTree())
manyTrees.append(Car()) //This makes an error "Car doesn't conform to expected type 'Tree'"
Upvotes: -5
Reputation: 1218
I think this is currently not possible. In my project I have the same issue with a ModelProducer.
protocol M: ModelType {}
protocol ModelProducerType {
associatedtype M: ModelType
var model: M? { get }
func produce()
}
struct Test: ModelType {}
class TestProducer: ModelProducerType {
var model: Test?
func produce() {
model = Test()
}
}
I use ModelType
as a ghost protocol. The problem is I cannot make a model producer that produces multiple ModelType
s, because of the same reason you discovered. The solution in this case was the following:
protocol M: ModelType {}
protocol ModelProducerType {
associatedtype M: ModelType
var model: [M] { get }
func produce()
}
struct Test: ModelType {}
class TestProducer: ModelProducerType {
var model: [Test] = []
func produce() {
model = [Test()]
}
}
This is more flexible from the start. I get rid of the optional variable and single model producers just have one item in the array. Maybe you can use a similar approach.
Upvotes: 1
Reputation: 6369
If there was an array of Photo
and Video
,what would you like to be?
1.Every element performs like what they are.
extension Array where Element : Feedable {
func foo() {
if Element.self == Photo.self {
} else {
}
}
}
2.The whole array performs as 'Video'.
extension Array where Element : Photo {
func foo() {
}
}
Upvotes: 3