首页 文章

专门针对协议继承的通用功能要求

提问于
浏览
5

我的代码中有一些协议层次结构,我有定义我使用的对象的协议和定义与这些对象一起使用的函数的协议 .

对象协议由其他对象协议继承,这些协议为原始协议添加了更多功能,使用它们的功能也是如此 . 问题是我找不到专门化函数的方法来只接受继承的参数 .

这里有一些代码来澄清我正在尝试做的事情:

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())

我想要做的是使 UseBProtocol 上的 use 函数只接受符合 B 的对象 . B 继承自 A ,但当我从 <T:A> 更改为 <T:B> 时,我收到一条错误消息,指出Manager不符合 UseAProtocol ,我必须将其更改回 <T:A> .

我知道我可以使用继承协议上的 associatedtypewhere 子句来实现这一点 - 这就是我今天使用的 - 但是我想将通用要求移到方法中,这样我就可以将它们全部组合在同一个结构中(我有很多这个层次结构和使用 associatedtype 我必须按层次结构使用一个结构 . 当有条件的一致性来到Swift时,这可能是 associatedtype ,但直到他们......

我也可以使用 as!UseBProtocol 实现上强制从 AB 的转换,但这是一个非常糟糕的解决方案,错误只会在运行时抛出 .

有没有办法实现我正在寻找的东西?

1 回答

  • 0

    看起来你正在寻找的是 UseAProtocol 中的 associatedType 而不是使 use 函数通用 .

    通过在 UseAProtocol 中声明关联类型并将 use 的函数签名更改为 static func use(_ obj: ProtocolType) ,您的代码编译得很好,您可以从 Manager 访问 foobar .

    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"
    

相关问题