Suppose we have a module with some private types that are not meant to be (directly) made use of by a client of the module. We can define a public protocol and implement that protocol with a private type:
public protocol PublicProtocol {
func print()
}
private struct PrivateStruct : PublicProtocol {
func print() {
Swift.print("this is a private instance")
}
}
Our module could then define some public method (or variable) to request the type conforming to this protocol:
public var PublicInstance: some PublicProtocol {
return PrivateStruct()
}
PublicInstance.print()
// This is a private instance.
Here, we use Swift Opaque Types to “hide” the actual return type from the client of this module; all the client sees is the PublicProtocol
interface. This is good, as long as we are interested in just an instance of the PrivateStruct
. If what we are interested in is the type of the PrivateStruct
, things don't look that easy:
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
We can't use an opaque return type here (AFAIK). Could we return the PublicProtocol
type itself?
public var PublicType: PublicProtocol.Type {
return PrivateStruct.self
}
PublicType.print()
// This is a private type.
That works, unless our PublicProtocol
defines an 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
In theory, we might (someday) have the ability to fix this with a public 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
We don't have functionality like this today (AFAIK).
We could just declare PrivateStruct
as a public
type:
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.
This “works”, except our private
type is now public
to the client of this module.
Is there any way to return a type (not an instance) as an opaque type? Is there any other support for doing something like this somewhere else in Swift?
Thanks.