语法帮助:将函数约束为泛型 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
上为 IntClass
和 StringClass
特定属性添加访问器(这样我就不必直接访问它们)。他们需要被限制在各自的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
的东西?)或者我是否必须解决该问题?
由于您在此处尝试访问的属性不依赖于 IntClass
或 StringClass
的类型参数 T
,因此您可以编写两个非通用协议 HasInt
和 HasString
:
protocol HasInt {
var int: Int { get }
}
protocol HasString {
var string: String { get }
}
extension IntClass: HasInt { }
extension StringClass: HasString { }
然后你可以约束协议,并通过协议访问 int
和 string
:
func int() -> Int where P: HasInt { object.int }
func string() -> String where P: HasString { object.string }
我有这样一个简化的结构:
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
上为 IntClass
和 StringClass
特定属性添加访问器(这样我就不必直接访问它们)。他们需要被限制在各自的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
的东西?)或者我是否必须解决该问题?
由于您在此处尝试访问的属性不依赖于 IntClass
或 StringClass
的类型参数 T
,因此您可以编写两个非通用协议 HasInt
和 HasString
:
protocol HasInt {
var int: Int { get }
}
protocol HasString {
var string: String { get }
}
extension IntClass: HasInt { }
extension StringClass: HasString { }
然后你可以约束协议,并通过协议访问 int
和 string
:
func int() -> Int where P: HasInt { object.int }
func string() -> String where P: HasString { object.string }