在 Swift 中,你能找到一个模块中遵守特定协议的所有类型吗?

In Swift, can you find all types in a module that adhere to a specific protocol?

在Swift4中,是否可以找到当前模块中所有遵循特定协议的类型?

例如,假设我定义了这个协议和这些 类:

protocol Animal{}
protocol Vehicle{}
protocol Favorite{}

class Dog : Animal{
}

class Cat : Animal, Favorite{
}

class Car : Vehicle{
}

class Bicycle : Vehicle, Favorite{
}

我想找到所有实现 Favorite 的类型。这可以在 C# 中轻松完成,但我不确定你是否可以在 Swift.

如果有帮助,我正在使用 Swift 4.

不可以在模块中获取 类 的名称。

你可以通过你的代码来计算,使用扩展协议来计算如下代码:)

protocol Animal{}
protocol Vehicle{}
protocol Favorite{
  func countImplement()
}

var totalImplement = 0
extension Favorite {
  func updateTotalImplement(){
    totalImplement += 1
  }
}

class Dog : Animal{
}

class Cat : Animal, Favorite{
   func countImplement(){
    this.updateTotalImplement()
  }
}

class Car : Vehicle{
}

class Bicycle : Vehicle, Favorite{
   func countImplement(){
    this.updateTotalImplement()
  }
}

我不相信 Swift 目前有 'native'(不依赖于 Objective-C 运行时)API 进行这种反射。

但是,如果您使用的是 Apple 平台(因此具有 Obj-C 互操作性),您可以获得所有 注册的列表Obj-C运行时,然后过滤那些符合给定协议的。这将适用于 Swift 类(甚至那些不继承自 NSObject 的),因为在引擎盖下 Swift 类 是建立在 Obj- 之上的C 类(当有 Obj-C 互操作时)。

因为这只适用于 类(不适用于结构或枚举),您可能希望限制您的协议,以便只有 类 可以符合它:

protocol Favorite : class {}

然后您可以使用 objc_copyClassList 执行以下操作:

import Foundation

protocol Animal {}
protocol Vehicle {}
protocol Favorite : class {}

class Dog : Animal {}
class Cat : Animal, Favorite {}
class Car : Vehicle {}
class Bicycle : Vehicle, Favorite {}

/// Invokes a given closure with a buffer containing all metaclasses known to the Obj-C
/// runtime. The buffer is only valid for the duration of the closure call.
func withAllClasses<R>(
  _ body: (UnsafeBufferPointer<AnyClass>) throws -> R
) rethrows -> R {

  var count: UInt32 = 0
  let classListPtr = objc_copyClassList(&count)
  defer {
    free(UnsafeMutableRawPointer(classListPtr))
  }
  let classListBuffer = UnsafeBufferPointer(
    start: classListPtr, count: Int(count)
  )

  return try body(classListBuffer)
}
//                               .flatMap in Swift < 4.1
let classes = withAllClasses { [=11=].compactMap { [=11=] as? Favorite.Type } }
print(classes) // [Bicycle, Cat]

这里我们在 UnsafeBufferPointer 上调用 compactMap(_:) 以取回表示符合 Favorite 的类型的元类型数组(即那些可以转换为存在元类型的元类型Favorite.Type).