[swift-evolution] protocol based invocation forwarding

Joe Groff jgroff at apple.com
Tue Dec 8 11:53:41 CST 2015


It'd definitely be awesome to support forwarding protocol conformances. One thing a forwarding design needs to consider is how to handle `Self` requirements in the forwarded protocol. If the protocol requirements consume `Self` types, you need a conversion operation to go from the forwarder to the forwardee type, such as the getter for the forwardee property.
If there are any requirements that return `Self` you'd need to additionally provide an initializer or factory function capable of building a new instance of the forwarder type from the forwardee.

-Joe

> On Dec 7, 2015, at 1:33 PM, David Owens II via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Often it is the case where one might want to implement a type that provides an interface but has inner components that actually handle the implementation. In those cases, we end up with a lot of boiler-plate code that simply turns around and invokes the on the instance.
> 
> Let’s take the example of class clusters:
> 
> private protocol _Cluster {
>     func description() -> String
> }
> 
> class Cluster: _Cluster {
>     
>     private var _instance: _Cluster
>     
>     init(name: String) {
>         _instance = _ClusterString(name: name)
>     }
>     
>     init(value: Int) {
>         _instance = _ClusterValue(value: value)
>     }
>     
>     // this is pure boiler-plate
>     func description() -> String {
>         return _instance.description()
>     }
> }
> 
> private class _ClusterString: _Cluster {
>     private var name: String
>     init(name: String) { self.name = name }
>     func description() -> String {
>         return "_ClusterString: \(name)"
>     }
> }
> 
> private class _ClusterValue: _Cluster {
>     private var value: Int
>     init(value: Int) { self.value = value }
>     func description() -> String {
>         return "_ClusterValue: \(value)"
>     }
> }
> 
> let s = Cluster(name: "a string")
> s.description()
> 
> let v = Cluster(value: 12)
> v.description()
> 
> 
> Now, it would be nice to not have to have to implement the boiler-plate (this example only has a single method, so the savings seem minimal).
> 
> class Cluster: _Cluster {
>     @forward(_Cluster, _instance)
> 
>     private var _instance: _Cluster
>     
>     init(name: String) {
>         _instance = _ClusterString(name: name)
>     }
>     
>     init(value: Int) {
>         _instance = _ClusterValue(value: value)
>     }
> }
> 
> The @forward(protocol, instance) attribute lets the compiler know that the _Cluster protocol should be forwarded to the _instance value. The compiler would then generate all of the implementation stubs. Refactoring is also made simple as API changes to _Cluster do not need to be manually reflected on the type.
> 
> Another way to solve this problem is with a sufficiently advanced macro system. But that is out-of-scope for v3. However, this seems like it could be a straight-forward enough implementation to support in the mean-time, with an easy path for removal/update if it were to be replaced by a macro system.
> 
> -David
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151208/a23c3de0/attachment.html>


More information about the swift-evolution mailing list