我需要在协议中创建泛型函数,并在扩展中使用默认实现。它的func应该与enum
RawRepresentable
项一起使用RawValue == String
。我试过了
protocol RequiresEnum: class {
associatedtype SectionIdentifierEnum: RawRepresentable // how this add restriction to RawValue == String
func test<T: SectionIdentifierEnum>(identifier: T) where T.RawValue == String
}
enum RequiresEnumDefault: String {
case `default`
}
extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum.RawValue == String {
typealias SectionIdentifierEnum = RequiresEnumDefault
func test<T: SectionIdentifierEnum>(identifier: T) where T.RawValue == String {
print(T.rawValue)
}
}
但我有错误
- &#39; SectionIdentifierEnum&#39;在这种情况下对类型查找不明确
- &#39; RawValue&#39;不是&#39; <&#39;
的会员类型
任何解决方案
答案 0 :(得分:5)
通常在协议上下文中覆盖泛型时,泛型类型持有者被视为associatedtype
协议可表示。在您的示例中,这将是SectionIdentifierEnum
,它充当受约束的类型的占位符。但是,SectionIdenfierEnum
本身不是协议,因此不能将其用作泛型方法中的类型约束。但 可以在test(...)
方法中将其用作类型本身。
现在,目前(Swift 3.1),您无法向associatedtype
添加复杂的类型约束。但是,您可以提供默认实现,仅适用于Self
从UIViewController
派生的情况,并通过将RequiresEnum
类型设置为具体来实现SectionIdentifierEnum
协议RequiresEnumDefault
类型。后者将确定此默认实现的关联RawValue
为String
,因为具体RawValue
类型的RequiresEnumDefault
为String
。
E.g:
// Swift 3.1
// ---------
// Types that implement this protocol mustn't necessarily use a
// `SectionIdentifierEnum` type where `SectionIdentifierEnum.RawValue`
// is constrained to equal `String`.
protocol RequiresEnum: class {
associatedtype SectionIdentifierEnum: RawRepresentable
func test(identifier: SectionIdentifierEnum)
}
enum RequiresEnumDefault: String {
case `default`
}
// This extension, however, is only available for types that use
// `RequiresEnumDefault ` as the concrete type of `SectionIdentifierEnum`
// (in which case `SectionIdentifierEnum.RawValue` is `String`).
extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum == RequiresEnumDefault {
func test(identifier: SectionIdentifierEnum) {
print(identifier.rawValue)
}
}
// Example usage.
class MyViewController : UIViewController, RequiresEnum {
typealias SectionIdentifierEnum = RequiresEnumDefault
// ...
}
let foo = MyViewController()
foo.test(identifier: RequiresEnumDefault.default)
// prints "default" (using extension:s default implementation)
以上,test(...)
的默认实现仅在SectionIdentifierEnum
等于具体类型RequireEnumDefault
时才可用(Self
来自UIViewController
...) 。如果您希望仅在SectionIdentifierEnum
任何枚举String
<{1}} 的情况下才能使用它,则相应地修改扩展的类型约束:
RawValue
一旦发布了Swift 4,您就可以根据Swift演化提案的实现向protocol RequiresEnum: class {
associatedtype SectionIdentifierEnum: RawRepresentable
func test(identifier: SectionIdentifierEnum)
}
enum RequiresEnumDefault: String {
case `default`
}
extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum.RawValue == String {
func test(identifier: SectionIdentifierEnum) {
print(identifier.rawValue)
}
}
// Example usage.
enum EnumWithStringRawValue: String {
case foo
}
class MyViewController : UIViewController, RequiresEnum {
typealias SectionIdentifierEnum = EnumWithStringRawValue
// ...
}
let foo = MyViewController()
foo.test(identifier: EnumWithStringRawValue.foo)
// prints "foo" (using extension:s default implementation)
:s添加更复杂的约束:
在这种情况下,上述内容可以修改为:
associatedtype
同样修改// Swift 4
// -------
// Here, all types that implement this protocol must use a
// `SectionIdentifierEnum` type where `SectionIdentifierEnum.RawValue`
// is equal to `String`.
protocol RequiresEnum: class {
associatedtype SectionIdentifierEnum: RawRepresentable
where SectionIdentifierEnum.RawValue == String
func test(identifier: SectionIdentifierEnum)
}
enum RequiresEnumDefault: String {
case `default`
}
// For the specific case where `SectionIdentifierEnum` equals
// `RequiresEnumDefault` (and where `Self` derives from `UIViewController`),
// this default implementation is readily available.
extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum == RequiresEnumDefault {
func test(identifier: SectionIdentifierEnum) {
print(identifier.rawValue)
}
}
// Example usage.
class MyViewController : UIViewController, RequiresEnum {
typealias SectionIdentifierEnum = RequiresEnumDefault
// ...
}
let foo = MyViewController()
foo.test(identifier: RequiresEnumDefault.default)
// prints "default" (using extension:s default implementation)
默认实现的约束,不仅仅是test(...)
等于SectionIdentifierEnum
的情况(但对于任何枚举:在这种情况下,我们知道这样的枚举将永远有由于协议定义中RequiresEnumDefault
的约束,RawValue
String
。
associatedtype