Swift 函数输入通用同时符合 Class 和协议
Swift Function Input Generic Conform To Both Class And Protocol
我正在尝试让一个函数采用符合 class 和协议的通用输入,以便处理一些属于 class 而另一些属于 class 的值代表。它适用于单个类型,但不适用于类型数组(符合 super class 和委托)。相反,编译器抛出错误“实例方法 'printValues(for:)' 要求 'MeasurementClass' 符合 'UnitDelegate'”
我添加了下面的代码,这会更有意义。只需将它放在 Swift Playground 中即可。如果你 运行 按原样,你可以看到它正确地打印了用户的距离和步数。如果您取消最后几行的注释,则无法对数组使用相同的函数。
我的目标是能够传递符合 UnitDelegate 和 MeasurementClass(又名 MeasurementObject 类型别名)的类型数组并处理值。我想要一个数组,因为我需要一堆符合 MeasurementObject 的不同 classes。
protocol UnitDelegate: class{
var units: [String: String] { get }
}
class MeasurementClass{
var imperial: Double!
var metric: Double!
convenience init(imperial: Double, metric: Double){
self.init()
self.imperial = imperial
self.metric = metric
}
}
typealias MeasurementObject = MeasurementClass & UnitDelegate
class Distance: MeasurementObject{
var units = ["imperial": "miles", "metric":"kms"]
}
class Steps: MeasurementObject{
var units = ["imperial": "steps", "metric":"steps"]
}
class User{
func printValues<T: MeasurementObject>(for type: T) {
print("\(type.imperial!) \(type.units["imperial"]!) = \(type.metric!) \(type.units["metric"]!)")
}
}
//This is what I'm trying to achieve in the for loop below
let distance = Distance(imperial: 30, metric: 48.28)
let steps = Steps(imperial: 30, metric: 30)
let user = User()
user.printValues(for: distance)
user.printValues(for: steps)
//let types = [distance, steps]
//
//for type in types{
// user.printValues(for: type)
//}
不是您问题的直接答案,但您只需要添加一个枚举以将测量类型存储到您的 class,并将计算的 属性 存储到 return对应的词典。不需要使用协议,协议组合,class and/or subclass 来完成你想做的事情:
struct AMeasurement {
let imperial: Double
let metric: Double
let kind: Kind
enum Kind { case distance, steps }
var units: [String: String] {
switch kind {
case .distance: return ["imperial": "miles", "metric":"kms"]
case .steps: return ["imperial": "steps", "metric":"steps"]
}
}
}
extension AMeasurement {
func printValues() {
print("\(imperial) \(units["imperial"]!) = \(metric) \(units["metric"]!)")
}
}
let distance = AMeasurement(imperial: 30, metric: 48.28, kind: .distance)
let steps = AMeasurement(imperial: 30, metric: 30, kind: .steps)
let types = [distance, steps]
for type in types {
type.printValues()
}
30.0 miles = 48.28 kms
30.0 steps = 30.0 steps
我正在尝试让一个函数采用符合 class 和协议的通用输入,以便处理一些属于 class 而另一些属于 class 的值代表。它适用于单个类型,但不适用于类型数组(符合 super class 和委托)。相反,编译器抛出错误“实例方法 'printValues(for:)' 要求 'MeasurementClass' 符合 'UnitDelegate'”
我添加了下面的代码,这会更有意义。只需将它放在 Swift Playground 中即可。如果你 运行 按原样,你可以看到它正确地打印了用户的距离和步数。如果您取消最后几行的注释,则无法对数组使用相同的函数。
我的目标是能够传递符合 UnitDelegate 和 MeasurementClass(又名 MeasurementObject 类型别名)的类型数组并处理值。我想要一个数组,因为我需要一堆符合 MeasurementObject 的不同 classes。
protocol UnitDelegate: class{
var units: [String: String] { get }
}
class MeasurementClass{
var imperial: Double!
var metric: Double!
convenience init(imperial: Double, metric: Double){
self.init()
self.imperial = imperial
self.metric = metric
}
}
typealias MeasurementObject = MeasurementClass & UnitDelegate
class Distance: MeasurementObject{
var units = ["imperial": "miles", "metric":"kms"]
}
class Steps: MeasurementObject{
var units = ["imperial": "steps", "metric":"steps"]
}
class User{
func printValues<T: MeasurementObject>(for type: T) {
print("\(type.imperial!) \(type.units["imperial"]!) = \(type.metric!) \(type.units["metric"]!)")
}
}
//This is what I'm trying to achieve in the for loop below
let distance = Distance(imperial: 30, metric: 48.28)
let steps = Steps(imperial: 30, metric: 30)
let user = User()
user.printValues(for: distance)
user.printValues(for: steps)
//let types = [distance, steps]
//
//for type in types{
// user.printValues(for: type)
//}
不是您问题的直接答案,但您只需要添加一个枚举以将测量类型存储到您的 class,并将计算的 属性 存储到 return对应的词典。不需要使用协议,协议组合,class and/or subclass 来完成你想做的事情:
struct AMeasurement {
let imperial: Double
let metric: Double
let kind: Kind
enum Kind { case distance, steps }
var units: [String: String] {
switch kind {
case .distance: return ["imperial": "miles", "metric":"kms"]
case .steps: return ["imperial": "steps", "metric":"steps"]
}
}
}
extension AMeasurement {
func printValues() {
print("\(imperial) \(units["imperial"]!) = \(metric) \(units["metric"]!)")
}
}
let distance = AMeasurement(imperial: 30, metric: 48.28, kind: .distance)
let steps = AMeasurement(imperial: 30, metric: 30, kind: .steps)
let types = [distance, steps]
for type in types {
type.printValues()
}
30.0 miles = 48.28 kms
30.0 steps = 30.0 steps