[swift-evolution] ability to derive a class from a struct or other value type

Haravikk swift-evolution at haravikk.me
Fri Jun 23 15:08:24 CDT 2017


> On 23 Jun 2017, at 16:20, Mike Kluev <mike.kluev at gmail.com> wrote:
> 
> on Fri Jun 23 05:26:11 CDT 2017 Haravikk swift-evolution at haravikk.me <http://haravikk.me/> wrote:
> 
> > Not sure what you mean by added indirection here, the following seems perfectly straightforward to me:
> > 
> > 	protocol Foo {
> > 		var someValue:Int { get set }
> > 		func a() -> Any?
> > 	}
> > 
> > 	extension Foo {
> > 		func a() -> Any? { return self.someValue }
> > 	}
> > 
> > 	struct ValueSemantics:Foo { var someValue:Int }
> > 	class ReferenceSemantics:Foo {
> > 		var someValue:Int { return nil }
> > 	}
> > 
> > There is no added access overhead here, the only difference is that the protocol itself leaves it up to 
> > implementations whether someValue is stored or computed.
> 
> in real cases there would be more variables:
> 
> //============
> protocol P1 {                       // #noise
>     var var1: Int { get set }       // #noise
>     var var2: Int { get set }       // #noise
>     // ...                          // #noise x 100
>     var var100: Int { get set }     // #noise
>     
>     func foo1() -> Int              // #noise
>     func foo2() -> Int              // #noise
>     // ...                          // #noise x 100
>     func foo100() -> Int            // #noise
> }
> 
> extension P1 {                      // #noise
>     func foo1() -> Int { return var1 * 2 }
>     func foo2() -> Int { return var2 * 2 }
>     // ...
>     func foo100() -> Int { return var100 * 2 }
> }
> 
> struct S1: P1 {
>     var var1: Int                   // #noise
>     var var2: Int                   // #noise
>     // ...                          // #noise x 100
>     var var100: Int                 // #noise
> }
> 
> class C1: P1 {
>     var var1: Int = 0               // #noise
>     var var2: Int = 0               // #noise
>     // ...                          // #noise x 100
>     var var100: Int = 0             // #noise
> }
> //============
> 
> 
> lots of noise and violations of DRY. you may try to mitigate it by putting all those storage into another struct, that was the indirection i was thinking about:

Maybe, but the whole point of the protocol is that it's a contract, it's up to the implementing types how the properties are actually stored (if at all); in that respect it's not noise, as it's necessary.

The shorthand you're proposing is effectively masquerading delegation as extension; I'm not sure making it look like extension is the right way to go, but delegation is absolutely something I support, just not in this style.

Currently there is a lot of boilerplate around things like type-erased wrappers, where you might get a class that looks like:

	class MyWrapper<S:Foo>:Foo {
		struct foo:S

		func someMethodOfFoo() { foo.someMethodOfFoo() }
		func someOtherMethodOfFoo() { foo.someOtherMethodOfFoo() }
	}

It's the same basic problem, except that I don't necessarily want everything to be implemented by my enclosed struct. This is why I'd prefer a solution that's more explicit about the fact that there's delegation going on, and more flexible about how things are delegated. This is what I mean:

	protocol Foo {
		var someValue:Int { get set }
		func someMethod() -> Int
	}

	struct ValueType:Foo {
		var someValue:Int
		func someMethod() { return self.someValue }
	}

	class ReferenceType:Foo {
		var foo:ValueType implements Foo // This is the important bit
	}

It's got one extra step, but is explicit that there's delegation involved, and without suggesting some kind of hierarchy that doesn't exist. In this case ValueType needn't even conform to Foo at all, just as long it has properties and methods that are a match; in this way we could potentially conform to Foo using multiple delegates that each implement a little bit of the protocol.

Another possible syntax is:

	class ReferenceType:Foo {
		delegate(Foo) var foo:ValueType
	}

This may be slightly better as it explicitly references to delegation, but it's the same idea; in the brackets you put one or more types, or members of types, that the property is a delegate for.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170623/78734a7e/attachment.html>


More information about the swift-evolution mailing list