修改抽象结构中的值
Modifying value in abstracted struct
我在使用结构和协议时遇到了这种情况,很想知道在这种情况下如何访问和修改值:
import Foundation
struct Garage {
var vehicles : [VehicleProtocol]
}
protocol VehicleProtocol {
var id: String { get }
}
protocol TwoWheelsProtocol: VehicleProtocol {
var id: String { get }
var uniqueTwoWheelsAttribut: String { get set }
}
struct TwoWheels: TwoWheelsProtocol {
var id: String
var uniqueTwoWheelsAttribut: String
}
protocol FourWheelsProtocol: VehicleProtocol {
var uniqueFourWheelsAttribut: String { get set }
}
struct FourWheels: FourWheelsProtocol {
var id: String
var uniqueFourWheelsAttribut: String
}
func printVehicules(of garage: Garage) {
for vehicle in garage.vehicles {
if vehicle is TwoWheelsProtocol {
let tw = vehicle as! TwoWheelsProtocol
print("\(tw.id) | \(tw.uniqueTwoWheelsAttribut)")
}
if vehicle is FourWheelsProtocol {
let tw = vehicle as! FourWheelsProtocol
print("\(tw.id) | \(tw.uniqueFourWheelsAttribut)")
}
}
}
let vehicle0 = TwoWheels(id: "0", uniqueTwoWheelsAttribut: "vehicle0")
let vehicle1 = FourWheels(id: "1", uniqueFourWheelsAttribut: "vehicle1")
var a = Garage(vehicles: [vehicle0, vehicle1])
printVehicules(of: a)
printVehicules(of: a)
结果是:
0 | vehicle0
1 | vehicle1
如何修改 vehicle0 uniqueTwoWheelsAttribut
使其具有:
0 | modified
1 | vehicle1
我可以用
if a is TwoWheelsProtocol {
let tw as! TwoWheelsProtocol
......
}
但由于转换结果在另一个变量中,因此修改不会影响原始值。
Classes have additional capabilities that structures don’t have:
- Reference counting allows more than one reference to a class instance.
所以 let tw as! TwoWheelsProtocol
总是创建一个新对象,因为 TwoWheels
是一个结构。为避免这种情况,您可以将 TwoWheels
变成 class:
class TwoWheels: TwoWheelsProtocol {
var id: String
var uniqueTwoWheelsAttribut: String
init(id: String, uniqueTwoWheelsAttribut: String) {
self.id = id
self.uniqueTwoWheelsAttribut = uniqueTwoWheelsAttribut
}
}
现在 let tw as! TwoWheelsProtocol
不会创建新副本,而只会创建对该对象的新引用。
你可以改进什么
要求 VehicleProtocol
只允许 classes 执行协议。通过这种方式,您可以确保强制转换和所做的更改确实更改了引用的对象,而不仅仅是它的副本。
protocol VehicleProtocol: class {
var id: String { get }
}
您可以使用更紧凑的铸造方法。
if var tw = vehicle as? TwoWheelsProtocol {
// Modify tw.
}
guard var tw = vehicle as? TwoWheelsProtocol else {
return
}
// Modify tw.
我在使用结构和协议时遇到了这种情况,很想知道在这种情况下如何访问和修改值:
import Foundation
struct Garage {
var vehicles : [VehicleProtocol]
}
protocol VehicleProtocol {
var id: String { get }
}
protocol TwoWheelsProtocol: VehicleProtocol {
var id: String { get }
var uniqueTwoWheelsAttribut: String { get set }
}
struct TwoWheels: TwoWheelsProtocol {
var id: String
var uniqueTwoWheelsAttribut: String
}
protocol FourWheelsProtocol: VehicleProtocol {
var uniqueFourWheelsAttribut: String { get set }
}
struct FourWheels: FourWheelsProtocol {
var id: String
var uniqueFourWheelsAttribut: String
}
func printVehicules(of garage: Garage) {
for vehicle in garage.vehicles {
if vehicle is TwoWheelsProtocol {
let tw = vehicle as! TwoWheelsProtocol
print("\(tw.id) | \(tw.uniqueTwoWheelsAttribut)")
}
if vehicle is FourWheelsProtocol {
let tw = vehicle as! FourWheelsProtocol
print("\(tw.id) | \(tw.uniqueFourWheelsAttribut)")
}
}
}
let vehicle0 = TwoWheels(id: "0", uniqueTwoWheelsAttribut: "vehicle0")
let vehicle1 = FourWheels(id: "1", uniqueFourWheelsAttribut: "vehicle1")
var a = Garage(vehicles: [vehicle0, vehicle1])
printVehicules(of: a)
printVehicules(of: a)
结果是:
0 | vehicle0
1 | vehicle1
如何修改 vehicle0 uniqueTwoWheelsAttribut
使其具有:
0 | modified
1 | vehicle1
我可以用
if a is TwoWheelsProtocol {
let tw as! TwoWheelsProtocol
......
}
但由于转换结果在另一个变量中,因此修改不会影响原始值。
Classes have additional capabilities that structures don’t have:
- Reference counting allows more than one reference to a class instance.
所以 let tw as! TwoWheelsProtocol
总是创建一个新对象,因为 TwoWheels
是一个结构。为避免这种情况,您可以将 TwoWheels
变成 class:
class TwoWheels: TwoWheelsProtocol {
var id: String
var uniqueTwoWheelsAttribut: String
init(id: String, uniqueTwoWheelsAttribut: String) {
self.id = id
self.uniqueTwoWheelsAttribut = uniqueTwoWheelsAttribut
}
}
现在 let tw as! TwoWheelsProtocol
不会创建新副本,而只会创建对该对象的新引用。
你可以改进什么
要求 VehicleProtocol
只允许 classes 执行协议。通过这种方式,您可以确保强制转换和所做的更改确实更改了引用的对象,而不仅仅是它的副本。
protocol VehicleProtocol: class {
var id: String { get }
}
您可以使用更紧凑的铸造方法。
if var tw = vehicle as? TwoWheelsProtocol {
// Modify tw.
}
guard var tw = vehicle as? TwoWheelsProtocol else {
return
}
// Modify tw.