> On Mar 11, 2017, at 3:12 PM, Edward Connell via swift-users
> <[email protected]> wrote:
>
> Observations about difining an object
> • Structs can't inherit and classes shouldn't inherit, final concrete
> types should be flat
> • Protocols need to be adopted by the final concrete type, otherwise
> constraint specializations aren't correctly applied
> This creates a really ugly code duplication situation when you have multiple
> object variants that adopt the same protocols.
>
> The storage declaration, common initialization, common didSet, etc... for
> protocol member variables must be duplicated for every instance.
> If I have 20 objects that have the same base set of 15 vars, this turns into
> a maintenance/bug nightmare.
>
> I noticed the use of GYB in the swift source code.
> I don't want to involve python in anything I do, and I don't want to mess up
> my code/build with all that stuff.
>
> It seems that an easy workaround would be an #include statement.
> The boiler plate can be put in a separate file and included wherever it's
> needed.
> One piece of code, one tool, one set of bugs.
>
> Has this been considered? Or is there a better way to handle this problem.
>
> Thanks, Ed
Without seeing the exact problem you're working on, I can't say for certain,
but this does seem like a very reasonable case for using inheritance. So I
disagree with your statement that "classes shouldn't inherit". Yes, if your
writing a framework, you might decide that some classes should not be
subclassed publicly (that was the entire argument about making final be the
default in Swift), but there's nothing wrong with still using inheritance for
those classes in your framework with only the deepest subclass being public and
then also marked final so it can't be subclassed.
I suppose you could argue that you want a value type (instead of a reference
type) so you want to use a struct and can't accomplish this with a struct other
than by repeating the same 15 vars and there's no way to "automate" that. If
that's the case, I guess I would argue the way to do it (which would require an
enhancement to Swift) would be to allow protocols (or a variation on protocols)
to define instance variables (vs. just requiring that the exist right now by
saying it must have a getter and possibly setter). I'm by no means a language
design expert so I don't know what other problems this might cause but I don't
think you're going to see any kind of #include statement in Swift.
Another option I might see some use for "partial inheritance" with structs
where the compiler would always know the exact type and determine which methods
would be called (i.e., no runtime vtable or objc_msgsend - it would all be
done statically by the compiler but you could declare one struct by building
upon another struct.
For example
struct Foo {
var x = 0
}
struct Bar: Foo { // so Bar also has an x instance variable
var y = 0
}
var b = Bar()
b.x = 3
b.y = 4
// but you couldn't do
var f: Foo = b // since Foo doesn't have a y
Again, I haven't fully thought through the implications and don't have enough
language design experience to know what other problems this might cause. And I
don't know if this is worth the increased cognitive load of having to check
multiple structs like you do with class inheritance to see what
methods/variables are defined in base classes.
But all I can say, is I don't see a good solution for your problem (other than
using inheritance) in the current version of Swift. I probably would declare a
protocol for those 15 variables and have each struct conform to that protocol
so you make certain you don't forget one of them in one of the structs but that
doesn't write the declarations for you.
Dave Reed
_______________________________________________
swift-users mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-users