gpt4 book ai didi

arrays - 如何在 Swift 中遍历不同类的所有属性?

转载 作者:行者123 更新时间:2023-11-28 07:55:05 25 4
gpt4 key购买 nike

假设我有一个名为 Car 的父类,它具有一些属性和一个实际上什么都不做的方法。

class Car {
var brandName : String
var yearOfCreation : Int
var color : String
var numberOfDoors : Int

func manipulateWithCar() {
}

init(brandName : String, yearOfCreation : Int, color : String, numberOfDoors : Int) {
self.brandName = brandName
self.yearOfCreation = yearOfCreation
self.color = color
self.numberOfDoors = numberOfDoors
}
}

我有两个子类,分别称为 SportCar 和 TankerCar。它们有自己独特的属性,父类的方法也被覆盖,现在它做了一些事情。

class SportCar : Car {
var turbo : Bool
var nitrousOxideEngine : Bool

override func manipulateWithCar() {
print("Putting turbo on your car...")
turbo = true
}

init(brandName: String, yearOfCreation: Int, color: String, numberOfDoors: Int, turbo : Bool, nitrousOxideEngine : Bool) {
self.turbo = turbo
self.nitrousOxideEngine = nitrousOxideEngine
super.init(brandName: brandName, yearOfCreation: yearOfCreation, color: color, numberOfDoors: numberOfDoors)
}
}

还有一个枚举方法。这并不重要,但您只想将其保留在作业中。

enum TankerForm {
case cilindrical
case quadratic
}

class TankerCar : Car{
var tankerFilledSize : Int
var tankerForm : TankerForm

init(brandName : String, yearOfCreation : Int,
color : String, numberOfDoors : Int, tankerVolum : Int, tankerForm : TankerForm) {
self.tankerForm = tankerForm
self.tankerFilledSize = tankerVolum
super.init(brandName: brandName, yearOfCreation: yearOfCreation, color: color, numberOfDoors: numberOfDoors)
}

override func manipulateWithCar() {
print("Loading 200 gallon of oil")
tankerFilledSize = 200
}
}

创建一些对象...

var kia = Car(brandName: "Rio", yearOfCreation: 2015, color: "Green", 
numberOfDoors: 4)

var toyota = Car(brandName: "Corolla", yearOfCreation: 2015, color:
"Red", numberOfDoors: 4)

var lamborgini = SportCar(brandName: "Aventador", yearOfCreation: 2018,
color: "Black", numberOfDoors: 2, turbo: false, nitrousOxideEngine:
false)

var mazeratti = SportCar(brandName: "Ghibli", yearOfCreation: 2017,
color: "Red", numberOfDoors: 4, turbo: true, nitrousOxideEngine: false)

var kamaz = TankerCar(brandName: "Kamaz", yearOfCreation: 2007, color:
"Yellow", numberOfDoors: 2, tankerVolum: 0, tankerForm: .cilindrical)

var belaz = TankerCar(brandName: "Belaz", yearOfCreation: 2003, color:
"White", numberOfDoors: 2, tankerVolum: 0, tankerForm: .quadratic)

用对象创建数组...

var carrsArray : [Car] = [kia, toyota]
var sportCarsArray : [SportCar] = [lamborgini, mazeratti]
var tankerCarsArray : [TankerCar] = [kamaz, belaz]

并使用 for 循环打印 Car 类对象的所有属性...

for value in carrsArray {
print("This car is \(value.brandName)")
print("The color is \(value.color)")
print("The car has \(value.numberOfDoors) doors")
print("The year of creation is \(value.yearOfCreation)")
print(" ")
}

正在使用 for 循环打印 SportCar 类对象的所有属性...

for value in sportCarsArray {
print("This car is \(value.brandName)")
print("The color is \(value.color)")
print("The car has \(value.numberOfDoors) doors")
print("The year of creation is \(value.yearOfCreation)")
if value.nitrousOxideEngine == true {
print("This car has Nitrous Oxide Engine")
} else {
print("There is no Nitrous Oxide Engine on this car.")
}
if value.turbo == true {
print("This car has turbo")
} else {
print("There is no turbo in this car.")
}
print(" ")
}

正在使用 for 循环打印 TankerCar 类对象的所有属性...

for value in tankerCarsArray {
print("This car is \(value.brandName)")
print("The color is \(value.color)")
print("The car has \(value.numberOfDoors) doors")
print("The year of creation is \(value.yearOfCreation)")
print("The tanker is filled with \(value.tankerFilledSize) lb of oil.")

if value.tankerForm == .cilindrical {
print("This car has cilindrical tanker form.")
} else {
print("This car has quadratic tanker form.")
}
print(" ")
}

现在是问题。有没有办法打印不同类的所有属性?我尝试创建一个包含三个数组的新数组:

var allClassesArrays = [carrsArray, sportCarsArray, tankerCarsArray]

但是在迭代过程中,它能够获取到父类的所有属性。

最佳答案

这就是反射的作用。您可以向 Car 类添加一个属性/方法,以列出当前类的所有属性以及父类(super class)的所有属性。当这个属性/方法被动态应用到子类时,它会给出你正在寻找的东西。

我们需要对 Mirror 进行扩展,以递归方式返回当前实例及其父类(super class)的所有属性,取自 Martin R's answer。 :

extension Mirror {
func toDictionary() -> [String: Any] {
var dict = [String: Any]()

// Attributes of this class
for attr in self.children {
if let propertyName = attr.label {
dict[propertyName] = attr.value
}
}

// Attributes of superclass
if let superclass = self.superclassMirror {
for (propertyName, value) in superclass.toDictionary() {
dict[propertyName] = value
}
}

return dict
}
}

class Car: CustomDebugStringConvertible {
// ...

var debugDescription: String {
let dict = Mirror(reflecting: self).toDictionary()
return dict.map { "\($0.key) = \($0.value)" }.joined(separator: "\n")
}
}

用法:

var allClassesArrays = [carrsArray, sportCarsArray, tankerCarsArray]
for car in allClassesArrays.flatMap({ $0 }) {
print(car.debugDescription, terminator: "\n\n")
}

您当然不必使 Car 符合 CustomDebugStringConvertible 或将属性命名为 debugDescription。我只是觉得它们很方便,因为调试器将在您键入 po car 时使用 debugDescription

关于arrays - 如何在 Swift 中遍历不同类的所有属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48492343/

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