使用泛型解决这个问题

时间:2017-07-03 15:27:51

标签: ios swift

使用通用LapCGPoint结构替换以下两个结构LapCLLocationLap的解决方案是什么?

两个结构都执行相同的操作,但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)
        }
    }
}

2 个答案:

答案 0 :(得分:2)

如果我的请求正确,你想在Swift中使用泛型实现一些东西,如果是这样的话,你可以做类似的事情:

Swift 3

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)
    }
}