语法帮助:将函数约束为泛型 class

Syntactic help: constraining functions to generic class

我有这样一个简化的结构:

protocol Protocol {
    associatedtype T
    var common: T { get }
}

class Superclass<T>: Protocol {
    let common: T
    init(common: T) { self.common = common }
}

class IntClass<T>: Superclass<T> {
    let int = 5
}

class StringClass<T>: Superclass<T> {
    let string = "String"
}

class Example<P: Protocol> {
    let object: P
    init(object: P) { self.object = object }
    func common() -> P.T { object.common }
    func int() -> Int where P == IntClass<Any> { object.int }
    func string() -> String where P == StringClass<Any> { object.string }
}

我想创建通用 class Example 的对象,其中一些对象包含同样通用 IntClass 的对象,而其他对象具有通用 StringClass目的。现在我想在 Example 上为 IntClassStringClass 特定属性添加访问器(这样我就不必直接访问它们)。他们需要被限制在各自的class。在我的示例中,这些将是 int()string()

虽然我的示例没有按预期工作:

let intExample = Example(object: IntClass(common: Double(1)))

//  (= expected)
intExample.common() // Double 1

//  (= expected)
intExample.string() // Instance method 'string()' requires the types 'IntClass<Float>' and 'StringClass<Any>' be equivalent

//  (= not expected)
intExample.int() // Instance method 'int()' requires the types 'IntClass<Float>' and 'IntClass<Any>' be equivalent

我也试过:

func int() -> Int where P == IntClass<P.T> { object.int }

这些编译器投诉:

- Generic class 'Example' requires that 'P' conform to 'Protocol'
- Same-type constraint 'P' == 'IntClass<P.T>' is recursive
- Value of type 'P' has no member 'int'

我试过了:

func string<T>() -> String where P == StringClass<T> { object.string }

,当使用 like intExample.string() 时会导致 Generic parameter 'T' could not be inferred(在 Instance method 'string()' requires the types 'IntClass<Double>' and 'StringClass<T>' be equivalent 旁边)。 我不希望 string() 出现在代码完成中的 Example<IntClass> 对象上。

是否有语法来完成我想要的(任何带有 typealias 的东西?)或者我是否必须解决该问题?

由于您在此处尝试访问的属性不依赖于 IntClassStringClass 的类型参数 T,因此您可以编写两个非通用协议 HasIntHasString:

protocol HasInt {
    var int: Int { get }
}

protocol HasString {
    var string: String { get }
}

extension IntClass: HasInt { }
extension StringClass: HasString { }

然后你可以约束协议,并通过协议访问 intstring:

func int() -> Int where P: HasInt { object.int }
func string() -> String where P: HasString { object.string }