Swift 专门化协议继承的通用功能需求
我的代码中有一些协议层次结构,其中有定义我使用的对象的协议,以及定义与此对象一起使用的函数的协议 对象协议由其他对象协议继承,这些协议向原始协议添加了更多功能,使用它们的功能也是如此。问题是我找不到专门化函数的方法,使其只接受继承的参数 这里有一些代码来说明我正在尝试做什么:Swift 专门化协议继承的通用功能需求,swift,generics,Swift,Generics,我的代码中有一些协议层次结构,其中有定义我使用的对象的协议,以及定义与此对象一起使用的函数的协议 对象协议由其他对象协议继承,这些协议向原始协议添加了更多功能,使用它们的功能也是如此。问题是我找不到专门化函数的方法,使其只接受继承的参数 这里有一些代码来说明我正在尝试做什么: protocol A { var foo: String { get set } } protocol B: A { var bar: String { get set } } struct Test:
protocol A {
var foo: String { get set }
}
protocol B: A {
var bar: String { get set }
}
struct Test: B {
var foo: String = "foo"
var bar: String = "bar"
}
protocol UseAProtocol {
static func use<T: A>(_ obj: T)
}
protocol UseBProtocol: UseAProtocol {
}
extension UseBProtocol {
//If I change the requirement to <T: B> this won't conform to `UseAProtocol`.
static func use<T: A>(_ obj: T) {
print(obj.foo)
// print(obj.bar) - Since obj does not conform to `B` I can't access ".bar" here without a forced casting.
}
}
struct Manager: UseBProtocol {
}
Manager.use(Test())
协议A{
var foo:String{get set}
}
B议定书:A{
变量栏:字符串{get set}
}
结构测试:B{
var foo:String=“foo”
var bar:String=“bar”
}
协议使用协议{
静态函数使用(uj:T)
}
协议使用协议:协议使用协议{
}
扩展使用协议{
//如果我将要求更改为,这将不符合“UseAProtocol”。
静态函数使用(uj:T){
打印(obj.foo)
//打印(obj.bar)-由于obj不符合'B',我无法在没有强制转换的情况下访问.bar。
}
}
结构管理器:UseBProtocol{
}
Manager.use(Test())
我要做的是使UseBProtocol
上的use
函数只接受符合B
的对象B
继承自A
,但当我从
更改为
时,我收到一个错误,说Manager不符合UseAProtocol
,我必须将其更改回
我知道我可以使用继承协议上的associatedtype
和where
子句来实现这一点——这就是我今天所使用的——但我想将通用需求转移到方法中,这样我就可以在同一个结构下将它们全部分组(我有很多这样的层次结构,通过使用associatedtype
我必须使用一个层次结构)。当条件一致性出现在Swift中时,使用associatedtype
,这是可能的,但直到它们
我还可以使用as!
强制在UseBProtocol
实现上从A
强制转换为B
,但这是一个非常糟糕的解决方案,只有在运行时才会抛出错误
有什么方法可以实现我想要的吗?看起来您实际上想要的是
UseAProtocol
中的关联类型,而不是使使用
函数通用
通过在UseAProtocol
中声明关联类型,并将use
的函数签名更改为static func use(j:ProtocolType)
您的代码编译良好,您可以从管理器访问foo
和bar
protocol AProtocol {
var foo: String { get set }
}
protocol BProtocol: AProtocol {
var bar: String { get set }
}
struct Test: BProtocol {
var foo: String = "foo"
var bar: String = "bar"
}
protocol UseAProtocol {
associatedtype ProtocolType
static func use(_ obj: ProtocolType)
}
protocol UseBProtocol: UseAProtocol {
}
extension UseBProtocol {
static func use(_ obj: BProtocol) {
print(obj.foo)
print(obj.bar)
}
}
struct Manager: UseBProtocol {
}
Manager.use(Test()) //prints both "foo" and "bar"
我是swift新手…但我可以给你一个指针,它可以同时打印foo和bar…扩展名UseBProtocol{static func use({obj:T){print(obj.foo)}static func use({obj:T){print(obj.foo)print(obj.bar)}我甚至不知道Swift,但我可以告诉你,仅仅使用方法签名可能是不可能的。你已经打破了Liskov替换原则:aUseBProtocol
应该在aUseAProtocol
有效的地方有效,而aUseBProtocol
只在aUseAProtocol
有效的地方工作s在所有A
s上。它(可能)会如果您翻转子类型并使UseAProtocol
成为UseBProtocol
的子类型,则可以工作。这几乎就是我要寻找的,但是如果我尝试向关联类型添加约束,使其符合“a”或“B”,则它将不符合。我添加了通用要求,因为我希望UseAProtocol仅使用AProtocol对象和UseBProtocol仅使用BProtocol(也是一个协议)对象。今天,我在代码中使用带有类似约束的associatedType,但由于它是类
要求,因此我需要为这个“a:B”示例使用一个结构,为类似的层次结构“C:D”使用另一个单独的类,为“E:F”使用另一个类。。。