gpt4 book ai didi

swift - Swift 协议(protocol)类型别名中的默认类型可能吗?

转载 作者:行者123 更新时间:2023-11-30 13:38:01 25 4
gpt4 key购买 nike

我通常会对一种或另一种编程范式的优点充满诗意,但今天我决定直接回答我的问题。所以我开始了……

我有 4-5 个类似的结构。在每个字段中,前 3 个字段几乎相同。我将这些结构存储在一个数组中。由于每个结构都是其自己的类型,并且由于我所听到的都是通用的面向协议(protocol)的编程,因此我决定让它们都符合一个协议(protocol)。然后我可以轻松地将它们保存在同一个数组中,如下所示:vartables: [DataHoldable]

所以,我知道我需要创建 5 个结构体,所有这些结构体必须共享三个成员:formatlength语言。这是我所讨论内容的简短示例:

// Imagine `TableA`, `TableB`, etc.
struct Table[A-D] : DataHoldable {
var format: UInt16
var length: UInt16
var language: UInt16
...
}

struct TableE : DataHoldable {
var format: Int32
var length: UInt32
var language: UInt32
...
}

如您所见,TableE 的所有字段都具有更宽的整数,并且其 format 字段经过签名以达到最佳效果。

所以,这就是我认为方便的typealias功能可以发挥作用的地方。

我做了一个像这样的协议(protocol):

protocol DataHoldable {

typealias FormatType = UInt16
typealias LengthType = UInt16
typealias LangType = UInt16

var format: FormatType { get }
var length: LengthType { get }
var language: LangType { get }

}

我认为,通过将默认类型 UInt16 分配给协议(protocol)的关联类型,我就不必在前 4 个结构中显式声明 UInt16,从而允许我绕过大量的重新输入(双关语)。我想可以做这样的事情:

struct Table[A-D] : DataHoldable {
var format: FormatType
var length: LengthType
var language: LangType
...
}

struct TableE : DataHoldable {
typealias FormatType = Int32
typealias LengthType = UInt32
typealias LangType = UInt32

var format: FormatType
var length: LengthType
var language: LangType
...
}

但是,情况似乎并非如此,因为无论我做什么,我都开始收到一个又一个错误。我什至创建了协议(protocol)的扩展,因为我认为人们能够在扩展中使用默认的关联类型。然而,在这样做时,我引入了新的更可怕的错误。

我尝试了大约 10 种不同的组合和/或黑客和/或诡计,但似乎没有任何效果。

所以我的问题是:如果不能真正使代码通用,那么能够“通用”代码有什么意义呢?我错过了什么吗?任何帮助、想法、想法、可能的路线等将不胜感激。谢谢!

最佳答案

正如我在评论中所写,请参阅this relevant Q & A关于尝试在协议(protocol)中为关联类型(此处为typealias)使用默认分配。

Quote from user fqdn:s answer

"... when conforming to a protocol, you cannot directly refer to an associated type that was declared only within that protocol

(note, however, that when extending a protocol the associated type is available, as you would expect) "

<小时/>

现在,尝试使用默认(分配的)关联类型并不是真正的“协议(protocol)的通用强度”;相反(作为示例,在本例中),可以在协议(protocol)扩展中定义的方法中使用关联类型来实现默认协议(protocol)实现。

protocol DataHoldable {
typealias FormatType
typealias LengthType
typealias LangType

var format: FormatType { get }
var length: LengthType { get }
var language: LangType { get }
}

extension DataHoldable {
func getFormatAndLengthAsTuple() -> (FormatType, LengthType) {
return(format, length)
}
}

任何符合 DataHoldable 协议(protocol)的类型都可以访问默认方法 getFormatAndLengthAsTuple()。此外,类型别名(关联类型)FormatTypeLengthTypeLangType 的实际类型不需要在类型一致性中显式声明 DataHoldable,可以通过属性formatlengthlanguage的类型推断 .

struct TableA : DataHoldable {
var format: UInt16 // FormatType inferred to be UInt16
var length: UInt16 // LengthType inferred to be UInt16
var language: UInt16 // LangType inferred to be UInt16

init() {
format = 1
length = 2
language = 3
}

// ...
}

struct TableE : DataHoldable {

var format: Int32 // FormatType inferred to be UInt16
var length: UInt32 // FormatType inferred to be UInt16
var language: UInt32 // FormatType inferred to be UInt16

init() {
format = 4
length = 5
language = 6
}

// ...
}

这里存在协议(protocol)和协议(protocol)扩展的一些“通用强度”

let fooA = TableA()
let fooE = TableE()
print(fooA.getFormatAndLengthAsTuple()) // (1, 2)
print(fooE.getFormatAndLengthAsTuple()) // (4, 5)
<小时/>

最后,请注意,在协议(protocol)蓝图中使用 typealias T = SomeActualType 是非常不寻常的;更常见的方法是在关联类型上包含一些类型约束typealias T: SomeTypeConstraint

例如,在您的情况下,将关联类型限制为 IntegerType 可能是合适的,允许您例如使用这些关联类型作为字典中的键,因为编译器知道所有符合 IntegerType 的类型也符合 EquatableHashable)。

protocol DataHoldable {
typealias FormatType: IntegerType
// ...

var format: FormatType { get }
var dict : [FormatType:String] { get set }
}

extension DataHoldable {
mutating func setFormatKeyFooValue() {
dict[format] = "foo"
}
}

struct TableA : DataHoldable {
var format: UInt16 = 42
var dict : [UInt16:String] = [:]

// ...
}

var fooA = TableA()
fooA.setFormatKeyFooValue()
print(fooA.dict) // [42: "foo"]

关于swift - Swift 协议(protocol)类型别名中的默认类型可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35876268/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com