使用通用LapCGPoint
结构替换以下两个结构LapCLLocation
和Lap
的解决方案是什么?
两个结构都执行相同的操作,但locations
数组和distanceTravelled
属性具有不同的类型。谢谢!
import CoreGraphics
import CoreLocation
struct LapCGPoint {
var locations = [CGPoint]()
var currentLocation: CGPoint? { return locations.last }
var previousLocation: CGPoint? {
return locations.count < 2 ? nil : locations[locations.count - 2]
}
var distanceTravelled: CGFloat
mutating func add(_ location: CGPoint) {
locations.append(location)
if let previousLocation = previousLocation, let currentLocation = currentLocation {
distanceTravelled += previousLocation.distanceTo(currentLocation) // distanceTo() is an extension to CGPoint
}
}
}
struct LapCLLocation {
var locations = [CLLocation]()
var currentLocation: CLLocation? { return locations.last }
var previousLocation: CLLocation? {
return locations.count < 2 ? nil : locations[locations.count - 2]
}
var distanceTravelled: Double
mutating func add(_ location: CLLocation) {
locations.append(location)
if let previousLocation = previousLocation, let currentLocation = currentLocation {
distanceTravelled += previousLocation.distance(from: currentLocation)
}
}
}
答案 0 :(得分:2)
如果我的请求正确,你想在Swift中使用泛型实现一些东西,如果是这样的话,你可以做类似的事情:
import UIKit
import CoreLocation
struct Lap<T: Any> {
var locations = [T]()
var currentLocation: T? {
return locations.count < 1 ? nil : locations[locations.count - 1]
}
var previousLocation: T? {
return locations.count < 2 ? nil : locations[locations.count - 2]
}
var distanceTravelled: Double
}
extension Lap where T: CGPoint {
mutating func add(_ location: T) {
self.locations.append(location)
if let previousLocation = self.previousLocation, let currentLocation = self.currentLocation {
self.distanceTravelled = self.distanceTravelled + previousLocation.distanceTo(currentLocation) // I don't know where the `distanceTo(...)` method is coming from...
}
}
}
extension Lap where T: CLLocation {
mutating func add(_ location: T) {
self.locations.append(location)
if let previousLocation = self.previousLocation, let currentLocation = self.currentLocation {
self.distanceTravelled = self.distanceTravelled + previousLocation.distance(from: currentLocation)
}
}
}
答案 1 :(得分:1)
因此,要做到这一点,首先需要定义通用结构可以使用的类型的要求。我们可以将其表达为协议:
protocol Point {
associatedtype Distance: FloatingPoint
static func distance(from: Self, to: Self) -> Distance
}
使用此协议,我们可以约束泛型结构的类型参数。在Point
结构的实现中只有Lap
协议中定义的操作可用:
struct Lap<T: Point> {
var locations: [T] = []
var distanceTravelled = T.Distance(0)
var currentLocation: T? { return locations.last }
mutating func add(_ location: T) {
let last = currentLocation
locations.append(location)
if let last = last {
distanceTravelled += T.distance(from: last, to: location)
}
}
}
要使用带有lap结构的任何类型,请为其添加扩展名以实现Point
协议的要求:
extension CLLocation: Point {
static func distance(from: CLLocation, to: CLLocation) -> Double {
return to.distance(from: from)
}
}
extension CGPoint: Point {
static func distance(from: CGPoint, to: CGPoint) -> CGFloat {
return from.distanceTo(to)
}
}