> On Mar 21, 2016, at 7:58 AM, Tino Heth via swift-evolution
> <[email protected]> wrote:
>
> Many languages which adopt the concept of value types don't allow subclassing
> for those, and so does Swift.
> Inheritance for structs is more complex than inheritance for classes, but the
> "final" limitation isn't the only possible solution, and Dave Abrahams told
> me in another thread that changing this rule might be considered in the
> future — so I'll risk getting taunted by the cool kids who are in favor of
> eliminating all ancient OOP-ideas ;-) and start a discussion.
>
> I guess most readers know about the low-level problems that arise when we
> switch from pointers (always the same size) to value types (size may vary),
> so I'll start with two possibilities for struct subtyping:
>
> newtype (see https://www.haskell.org/tutorial/moretypes.html
> <https://www.haskell.org/tutorial/moretypes.html> — or just read on if you
> are scared by Haskell ;-)
>
> When a subtype does not add any stored properties to its superclass (memory
> layout doesn't change), there is no difference at the level of object code —
> only the type checker may stop you from using those two types interchangeably.
As I understand it, a single argument struct ends up being as “free” as a
newtype is in Haskell (modulo resiliency concerns), or close to it. For
instance, my understanding is that the Int type is a single argument struct
wrapper around a lower-level numeric type.
> Some use cases:
> - In Cocoa, there is no separate class for (file system) paths; instead,
> there are some additions to NSString. String doesn't have those abilities,
> and imho methods like "stringByAppendingPathExtension" deserve a separate
> Path-struct, so that those special methods don't pollute the method list of
> String (URL is the future, so that example is somewhat out-of date).
> - You could impose incompatibility on numeric types to ensure that your
> calculations use correct quantities. Although this can be annoying (Float vs.
> CGFloat), decorating numbers with quantity/unit could eliminate bugs that had
> really disastrous consequences in the past.
> - Increased comfort for floating-point math:
> struct CustomDouble: Double
>
> func == (a: CustomDouble, b: CustomDouble) -> Bool {
> return abs(a.value - b.value) < 0.01
> }
> (no need to specify tolerance for each comparison)
>
> Full subtyping
>
> As long as you don't cross module borders, it wouldn't be that complicated to
> add inheritance without restrictions.
> imagine you have a "Customer"-type and a "Employee"-type to store personal
> data (name, address…).
> Those data objects are perfect candidates to be implemented as structs, but
> they also cry for a "Person"-superclass, so you are forced to either
> duplicate code, or to implement your objects as reference types.
There’s a number of wrinkles that are worth considering—for instance, are you
doing nominal or structural subtyping? The value-nature of structs suggests
that structural subtyping would be useul. However, structs are already nominal
types (unlike tuples).
Some compelling use cases for why a class doesn’t suffice and you really need a
struct would enhance a full proposal.
Cheers,
-Colin
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution