【问题标题】:Making a Swift Array conform to a Protocol使 Swift 数组符合协议
【发布时间】:2016-03-31 02:59:00
【问题描述】:

假设某些项目可以出现在Feed 中,只要它们实现了Feedable 协议定义的必要属性。我们还假设Photo 对象是值得提要的:

extension Photo: Feedable { }

是否可以说这些照片中的Array 也可能是Feedable

extension [Photo] : Feedable

或者我是否总是需要某种包装对象,例如PhotoAlbum,以符合Feedable

编辑

再次重复,我很好奇我是否只能制作Photo 对象Feedable 的数组。不制作任何内容类型的 Array Feedable,不制作 Feedables 本身的数组 Feedable(如果您需要,这两者都作为以下解决方案提供)。

换句话说,一个解决方案(我怀疑存在)将允许我定义一个 Feedable 类型的变量,结果如下:

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

也许this gist(当然不会编译)更清楚地表明了意图。

【问题讨论】:

  • extension Array where Element: Feedable { ... }
  • @LeoDabus 我希望为Photo 对象数组与其他Feedable 类型数组提供Feedable 协议的特定实现。例如,照片数组可能会提供一个feedDescription,它不同于Video 对象数组。
  • @matt Feedable 协议将为Photo 与一组Photos 提供不同的feedDescription 实现。例如。 “添加了一张照片”与“添加了 5 张照片”。假设我只获得了值得供稿的项目(一张照片、一段视频或其中的一组)。
  • @BenPackard extension _ArrayType where Generator.Element == Photo { ... }
  • @matt 在我看来,这与不输入所有数组 [AnyObject] 的原因相同 - 只是认为只有照片、视频和其他处理类型符合的数组会很好我可以扔掉 Feedable 类型的对象,因为我知道它们总是能够给我合理的提要描述。

标签: ios arrays swift protocols


【解决方案1】:

您可以通过这种方式实现您的目标:

斯威夫特 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() {    
    }
}

【讨论】:

  • 这很好,但我不认为它符合所有标准。具体来说,我的代码 sn-p 中的最后一个示例:“即使数组的内容本身是可馈送的,这还不够。例如,视频是可馈送的,但视频数组不是。”。在您的实现中,字符串数组是 Feedable 仅仅是因为 String 本身是 Feedable。
【解决方案2】:

如果有PhotoVideo 的数组,你想成为什么?

1.每个元素的表现都像他们一样。

extension Array where Element : Feedable {
    func foo() {
        if Element.self == Photo.self {

        } else {

        }
    }
}

2.整个数组表现为“视频”。

extension Array where Element : Photo {
    func foo() {

    }
}

【讨论】:

  • 我想要前者,但不必允许任何类型的所有数组都是Feedable
  • @BenPackard 元素是数组的泛型类型。只有当您的数组确认所有条件时,带有条件的扩展才会起作用。
  • @ben-packard 提议的解决方案中的“where”子句意味着此扩展仅适用于数组中的元素类型符合 Feedable 协议的数组,而不是“任何类型的所有数组” '
  • @ScottThompson 这不是我要问的。我想知道如何制作可喂养的照片数组,而不是制作可喂养的可喂养数组。我不相信这是可能的。
【解决方案3】:

我认为目前这是不可能的。在我的项目中,我对 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()
    }
}

我使用ModelType 作为幽灵协议。问题是我无法制作一个产生多个ModelTypes 的模型生成器,原因与您发现的相同。在这种情况下,解决方案如下:

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()]
    }
}

这从一开始就更加灵活。我摆脱了可选变量,单个模型生产者在数组中只有一项。也许您可以使用类似的方法。

【讨论】:

    【解决方案4】:

    您可以创建一个数组来符合这样的协议:

    typealias PhotoArray = [Photo]
    
    extension PhotoArray: Feedable {}
    

    【讨论】:

      【解决方案5】:

      我没有在操场上尝试,但也许你可以简单地制作一个 Feedable 数组:

      var myPhotosArray = [Feedable]()
      

      那么所有实现 Feedable 协议的东西都将被允许在数组中。如果您只想要一个照片数组,您仍然可以将您的照片对象子类化为一个 FeedablePhoto 对象。

      在 Playground 中试试这个,而不是在没有测试的情况下投反对票。 没有任何理由和解释的严重 3 downvote...

      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'"
      

      【讨论】:

      • 在这篇文章上做-1之前你有没有尝试过?我试过了,它奏效了。
      • 我自己没有-1,但这根本不能回答问题。我认为这就是它被否决的原因。
      • 据我了解,确实如此。只有实现 Feedable 协议的类才能添加到数组中。问题是:“是否可以说这些照片的数组也可能是可喂食的?”我想我的答案不容易理解,我没有用 Swift 3 而是用 Swift 2 尝试过这个。只需让一个 Photo 类实现协议就可以了。
      猜你喜欢
      • 2021-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多