swift - 带有可选元素的扩展可选数组。甚至可能吗?
问题描述
我有一个协议FooProtocol
。和一堂课Bar<Foo:FooProtocol>
。var mess: [Foo?]?
在一个类中保留一个数组,[foo1, foo2, nil, foo3...]
或者nil
我尝试对此数组进行扩展以计算新的 Foo 对象。我更喜欢有协议,因为 Foos 可能是从外部世界传递的非常不同的对象。
protocol FooProtocol {
....
init(from heaven: Int)
}
extension Optional where
Wrapped: Collection,
Wrapped.Element == Optional,
Wrapped.Element.Wrapped: FooProtocol // 'Wrapped' is not a member type of 'Wrapped.Element'
{
var united: Wrapped.Element.Wrapped { // Nope
let i = ...
return Wrapped.Element.Wrapped(from: i) // Nope
}
}
class Bar<Foo:FooProtocol> {
var mess: [Foo?]?
init (with mess: [Foo?]?) {
self.mess = mess
}
var important: Foo {
return mess.united
}
}
有任何想法吗?我被封锁了。
编辑1:
在 Leo 提出建议后,我更改了部分代码。但还是卡住了。这次来自 Playgrounds 的更多代码。
任何可以转换为“[Double]”的对象。可以是颜色(如 RGBA)、Bezier 曲线、正方形等等……
public protocol FooProtocol {
var atomized: () -> [Double] {get}
static var count: Int {get}
init(_ array:[Double])
init()
}
public extension Array where Element: FooProtocol {
var average: Element {
var resultAtoms: [Double] = []
let inputAtoms = self.map {$0.atomized()}
for i in 0..<Element.count {
let s = inputAtoms.reduce(into: 0.0, {$0 += $1[i]}) / Double (Element.count)
resultAtoms.append(s)
}
return Element(resultAtoms)
}
}
extension Optional where
Wrapped: Collection,
Wrapped.Element == Optional<FooProtocol>
{
typealias Foo = Wrapped.Element.Wrapped // Doesn't work. How to get class?
var average: Foo { // I cannot use Wrapped.Element, it's Optional
if let thatsList = self {
let withOptionals = Array(thatsList) // OK, its [Optional<FooProtocol>]
let withoutOptionals = thatsList.compactMap({$0}) // OK, its [FooProtocol]
// This is funny, called from class works and makes 'bingo'.
return withoutOptionals.average // Error: Value of protocol type 'FooProtocol' cannot conform to 'FooProtocol'; only struct/enum/class types can conform to protocols
} else {
return Foo() // Hello? init Wrapped? Foo? How to get Foo()?
}
}
}
class Bar<Foo:FooProtocol> {
var mess: [Foo?]?
init (with mess: [Foo?]?) {
self.mess = mess
}
func workOn() {
let z:Foo = mess.average // OK, I can make 'mess.average ?? Foo()' but prefer not do it
}
// Thats OK
func workHard() { // To prove 'Array extension where Element: FooProtocol' works
if let messExist = mess {
let withoutOptionals = messExist.compactMap({$0})
let bingo = withoutOptionals.average //It's OK
}
}
}
class SomeFoo : FooProtocol {
static var count = 3
required init() {
a = 0
b = 0
c = 0
}
required init(_ array: [Double]) {
self.a = Int(array[0])
self.b = Float(array[1])
self.c = array[2]
}
var atomized: () -> [Double] {
return {return [Double(self.a), Double(self.b), self.c]}
}
var a: Int
var b: Float
var c: Double
}
let aFoo = SomeFoo([1, 2, 3])
let bFoo = SomeFoo([7, 9, 1])
let cFoo = SomeFoo([2, 6, 5])
let barData = [nil, aFoo, nil, bFoo, cFoo]
let barWithData = Bar(with: barData)
let barWithoutData = Bar<SomeFoo>(with: nil)
也许我应该忘记扩展数组并在类中创建一些函数(我几乎可以肯定我会在其他地方需要这些函数)
编辑 2
即使我尝试简化并为 Array 进行扩展,我也发现了麻烦。
extension Array where
Element == Optional<FooProtocol>
{
func averageNils <Foo: FooProtocol>() -> Foo {
let withOptionals = Array(self) // OK, its [Optional<FooProtocol>]
let withoutOptionals = self.compactMap({$0}) // OK, its [FooProtocol]
return withoutOptionals.average as! Foo // Error: Value of protocol type 'FooProtocol' cannot conform to 'FooProtocol'; only struct/enum/class types can conform to protocols
}
}
解决方案
根据我的理解,它应该像你一样工作,但是人们永远不知道在 swift 编译器世界中会发生什么(尤其是错误消息)。
无论如何,您可以通过将更精确地Wrapped.Element.Wrapped
指定为a来避免深入挖掘 :Wrapped.Element
Optional<FooProtocol>
protocol FooProtocol {}
class Foo : FooProtocol {}
extension Optional where
Wrapped: Collection, //OK
Wrapped.Element == Optional<FooProtocol> // still good
{
var unfied: Wrapped.Element // Should be 'Foo' if self is '[Foo?]?' {
{
return 1 == 0 ? nil : Foo()
}
}
推荐阅读
- c++ - 如何将值设置为头文件中声明的指针
- excel - How to loop to copy data following blank cells in a column and paste it to last empty column?
- time-series - 带有掩码特征的股票价格预测
- android - Android lint 导出到 HTML 不适用于大量检查结果
- regex - 如何使用 HTML5 验证日期模式
- c# - 在 iis express 中运行 asp.net core mvc 项目时遇到问题
- mysql - 如果日期不存在,则获取给定日期的最后一行
- javascript - 如果我在对话框中打开 ASP RadioButtons,服务器端 OnCheckedChanged 不起作用
- php - mpdf 生成的文件总是要求在 acrobat 中关闭之前保存更改
- python - 使用 xlsxwriter 将 Excel 中的一组单元格的边框更改为粗框边框