Swift与Ankit的泛型
在谈论其他任何事情之前,让我们先回顾一下您的过去。 如何教你和洗脑。 假设您需要打印数组中的每个元素,您可能已经做到了。
let stringArray = ["1", "2", "3", "4"]
let intArray = [1, 2, 3, 4]
let doubleArray = [1.1, 1.2, 1.3, 1.4]
好吧,让我们打印。
func printStringFromArray(a: [String]) {
for s in a {
print(s)
}
}
func printIntFromArray(a: [Int]) {
for i in a {
print(i)
}
}
func printDoubleFromArray(a: [Double]) {
for d in a {
print(d)
}
}
上面的代码非常糟糕。 糟透了 每个函数仅采用一种特定类型的数组。 它像论据一样重复。 我们讨厌。 是否可以有一个函数允许您输入类型未定义的任何参数?
这是一个反问。 当然。 如果没有,我可能没有写这篇文章。 让我们部署。
泛型,你野蛮
Swift语言提供了“通用”功能来编写灵活且可重用的函数和类型。 泛型用于避免重复并提供抽象。 Swift标准库是使用泛型代码构建的。 Swifts的“数组”和“字典”类型属于通用集合。 在数组和字典的帮助下,将数组定义为容纳“ Int”值和“ String”值或任何其他类型。
好。 首先,如果要使函数通用,只有一条规则。 您需要做的只是将放在函数名称旁边。 让我们来看看,
func savageGenerics(value: anything) {
print(value)
}
savageGenerics(value: 123) // Int: Damn 😀
savageGenerics(value: "Ankit") // String: Killing it 😲
savageGenerics(value: 123.12) // Double: Whoa 😵
savageGenerics(value: true) // Bool: I'm done 😱
只是忍受我一秒钟。 澄清一下,当您将任何类型输入value
,Swift都会根据输入自动确定value
的类型。 例如,如果您致电,
savageGenerics(value: “Ankit”)
value
类型现在为String
,可以在函数中使用。 如果你打电话
savageGenerics(value: false)
value
类型现在为Bool
。 希望您现在对我清楚。 当然,您不必将其称为anything
。 您可以随心所欲。
func savageGenerics(value: T) {
print(value)
}
让我们申请
太好了,既然我们了解了泛型是什么,那么就让我们开始表演吧。
func printElement(array: [T]) {
for element in array {
print(element)
}
}
所以,您所要做的就是
printElement(array: doubleArray) // 1.1 1.2 1.3 1.4
printElement(array: intArray) // 1 2 3 4
printElement(array: stringArray) // "1" "2" "3" "4"
一个功能可以解决所有问题。 这就是为什么我称其为野蛮人。 如果您不熟悉此术语,请参阅《都市词典》。
因此,让我们提出苹果对泛型的定义,
通用代码使您可以编写灵活,可重用的函数和类型,这些函数和类型可以根据您定义的要求与任何类型一起使用。 您可以编写避免重复的代码,并以清晰抽象的方式表达其意图。 — Swift编程语言
实际上,用于与数组和字典进行交互的Swift库具有许多通用代码。
结构体通用
泛型不仅适用于函数,而且适用于类和结构。 假设有一个名为Family
的结构,其数组属性称为members
。 您可以在数组中添加或删除元素。
struct Family {
var members = [String]()
mutating func push(member: String) {
members.append(member)
}
mutating func pop() -> String {
return members.removeLast()
}
}
如果要修改属性,则需要 关键字 mutating
。 由于要为 members
添加和删除元素,因此 必须 为这些函数 添加 mutating
。
再次,问题
问题是,您只能将String
追加到元素上,因为不仅members
被预定义为[String]
而且pop()
和push()
仅允许使用String
。 这不是通用的。 这不是很酷。 如果要创建一个名称为Int
的族,则必须创建整个结构。
让我介绍一个通用结构,该结构允许您插入任何内容。 与我们使用的功能类似,将放在其名称旁边。
struct SavageFamily {
var members = [T]()
mutating func push(member: T) {
members.append(member)
}
mutating func pop() -> T {
return members.removeLast()
}
}
因此,现在让我们创建一个对象,其类型可以是1.明确声明或2.推断。
1.明确陈述
让我们使用SavageFamily
结构创建一个对象。 就像一个函数一样,您必须在其名称中插入 。 例如,
var myFam = SavageFamily()
var numberFam = SavageFamily()
您已经声明myFam
实例将只能与Int
String和numberFam
进行交互。 好处是您不需要创建两个单独的结构即可产生上面的结果。 所以,让我们互动。
// myFam
myFam.members = ["Mom", "Dad", "Sister", "Ankit"]
myFam.push(member: "Dog")
// numberFam
numberFam.members = [1, 2, 3, 4, 5]
numberFam.pop()
2.推断
创建对象时,不必像创建变量一样指定其类型。 Swift很聪明,足以猜测其类型和存储方式。 例如,
let yolo = "Ankit" // yolo is String
同样,它也适用于通用结构。 因此,您可以创建一个通用对象,例如
let friendFam = SavageFamily(members: [“Cash outside”, “Bruh”])
let trueFam = SavageFamily(members: [false, false, false])
显然, friendFam
只能与String
交互,而trueFam
只能与Bool
交互。 使用通用结构创建对象时,不必处理那些 。
通用扩展
不仅如此,实际上您还可以为通用结构或类添加扩展。
如果您不熟悉扩展程序,请随时观看我的YouTube视频
让我们添加一个获取第一个元素的属性。
extension SavageFamily {
var firstElement: T? {
if members.isEmpty {
return nil
} else {
return members[0]
}
}
}
现在,您可以在对象中自由使用该属性
let tigerFam = SavageFamily()
tigerFam.firstElement // nil
let lionFam = SavageFamily(members: ["Father", "Mother"])
lionFam.firstElement // "Father" Optionals
大。 您已经走了很长一段路。 感谢您的关注和爱心。 让我们抓住最后一块。
类型约束
如果您还记得创建通用函数的时间,
func doSomething(array: [HelloKitty]) {}
func doNothing(sth: T) {}
无论如何,您都可以添加任何内容。 您可以添加任何命名的对象。 但是,如果您想限制为几种类型呢? 如果您仅限制只能接受某些类的功能怎么办?
在T
旁边,您可以指定您只能使用的类型。 让我们创建一个名为LOL
的类。
Foo和boo太无聊了
class LOL {}
好吧,让我们创建一个只能接受LOL的泛型函数
func addClassOnly(array: [T]) {
}
addClassOnly(array: [LOL(), LOL(), LOL()]) // Works
addClassOnly(array: ["Lol", "Lol", "Lol"]) // Doesn't Work
只是让您知道,如果您将Lol
这样子类化,
class ChildLOL: LOL {}
您仍然可以添加到函数,该函数也可以接受类型为LOL
值。
addClassOnly(array: [LOL(), LOL(), ChildLOL(), ChildLOL()])
现在就这样。
最后的评论
从现在开始,您将看到很多和
。 我仅介绍了泛型的理论方面,但是至少您知道遇到野蛮人时正在阅读的内容。 如果您认为自己喜欢这篇文章或学到了一些新知识,请在下面♥♥或评论,以表示支持和喜爱!