Swift:有没有办法将 *type*(而不是 *instance*)作为opaque类型返回?

b1zrtrql  于 9个月前  发布在  Swift
关注(0)|答案(1)|浏览(83)

假设我们有一个模块,它有一些私有类型,这些私有类型并不打算被模块的客户端(直接)使用。我们可以定义一个公共协议,并用私有类型实现该协议:

public protocol PublicProtocol {
  func print()
}

private struct PrivateStruct : PublicProtocol {
  func print() {
    Swift.print("this is a private instance")
  }
}

字符串
然后,我们的模块可以定义一些公共方法(或变量)来请求符合此协议的类型:

public var PublicInstance: some PublicProtocol {
  return PrivateStruct()
}

PublicInstance.print()
//  This is a private instance.


在这里,我们使用Swift Opaque Types来“隐藏”这个模块的客户端的实际返回类型;所有客户端看到的是PublicProtocol接口。只要我们只对PrivateStruct的一个 * 示例 * 感兴趣,这是很好的。如果我们感兴趣的是PrivateStruct的 * 类型 *,事情就不那么容易了:

public protocol PublicProtocol {
  static func print()
}

private struct PrivateStruct : PublicProtocol {
  static func print() {
    Swift.print("This is a private type.")
  }
}

public var PublicInstance: some PublicProtocol.Type {
  return PrivateStruct.self
}
//  error: an 'opaque' type must specify only 'Any', 'AnyObject', protocols, and/or a base class


我们不能在这里使用不透明的返回类型(AFAIK)。我们可以返回PublicProtocol类型本身吗?

public var PublicType: PublicProtocol.Type {
  return PrivateStruct.self
}

PublicType.print()
//  This is a private type.


除非我们的PublicProtocol定义了一个associatedtype,否则这是可行的:

public protocol PublicProtocol {
  associatedtype ChildType
  
  static func print()
}

private struct PrivateStruct : PublicProtocol {
  typealias ChildType = Void
  
  static func print() {
    Swift.print("This is a private type.")
  }
}

//  error: protocol 'PublicProtocol' can only be used as a generic constraint because it has Self or associated type requirements


从理论上讲,我们可能(有一天)有能力用一个公共的typealias来解决这个问题:

public typealias PublicType : some PublicProtocol = PrivateStruct

error: 'some' types are only implemented for the declared type of properties and subscripts and the return type of functions


我们现在还没有这样的功能(AFAIK)。
我们可以直接将PrivateStruct声明为public类型:

public protocol PublicProtocol {
  associatedtype ChildType
  
  static func print()
}

public struct PrivateStruct : PublicProtocol {
  public typealias ChildType = Void
  
  public static func print() {
    Swift.print("This is a private type.")
  }
}

public typealias PublicType = PrivateStruct

PublicType.print()
//  This is a private type.


这“起作用”了,除了我们的private类型现在对于这个模块的客户端是public
有没有办法把一个 type(不是一个 instance)作为一个不透明的类型返回呢?在Swift中有没有其他的方法支持这样做呢?
谢谢.

qcbq4gxm

qcbq4gxm1#

public protocol PublicProtocol {
  associatedtype PrivateConstraint
  
  static func print()
}

private struct PrivateStruct : PublicProtocol {
  typealias PrivateConstraint = Void
  
  static func print() {
    Swift.print("This is a private type.")
  }
}

public var PublicType: any PublicProtocol.Type {
  return PrivateStruct.self
}

PublicType.print()
//  This is a private type.

字符串
这段代码使用Swift 5.6中引入的any关键字。

相关问题