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替换原则:a
UseBProtocol
应该在a
UseAProtocol
有效的地方有效,而a
UseBProtocol
只在a
UseAProtocol
有效的地方工作s在所有
A
s上。它(可能)会如果您翻转子类型并使
UseAProtocol
成为
UseBProtocol
的子类型,则可以工作。这几乎就是我要寻找的,但是如果我尝试向关联类型添加约束,使其符合“a”或“B”,则它将不符合。我添加了通用要求,因为我希望UseAProtocol仅使用AProtocol对象和UseBProtocol仅使用BProtocol(也是一个协议)对象。今天,我在代码中使用带有类似约束的associatedType,但由于它是
要求,因此我需要为这个“a:B”示例使用一个结构,为类似的层次结构“C:D”使用另一个单独的类,为“E:F”使用另一个类。。。