[swift-evolution] [Proposal] Sealed classes by default

L. Mihalkovic laurent.mihalkovic at gmail.com
Sat Jul 2 07:35:44 CDT 2016


Inline
Regards
(From mobile)

On Jul 2, 2016, at 10:51 AM, Brent Royal-Gordon <brent at architechies.com> wrote:

>> On Jul 2, 2016, at 12:42 AM, L. Mihalkovic <laurent.mihalkovic at gmail.com> wrote:
>> 
>> This is a situation I often run into in jave where I would use an enum to create a finite set of constants to be passed (say action identifers). But then this makes it very difficult for external modules to extend the core set of actions locally. So i generally windup with an enum and an interface (the enum implements the interface).
> 
> Sure. I would argue that that's the exact right approach to take for this kind of thing. For instance, for storyboard segue identifiers, I would write something like this:
> 
>    open protocol SegueIdentifierProtocol: RawRepresentable where RawValue == String {}
> 
>    open protocol SeguePerformable {
>        associatedtype SegueIdentifier: SegueIdentifierProtocol
>        
>        // Hooks
>        func shouldPerformSegue(with identifier: SegueIdentifier, sender: AnyObject?) -> Bool
>        func prepare(for segue: UIStoryboardSegue, with identifier: SegueIdentifier, sender: AnyObject?)
>    }
> 
>    public extension SeguePerformable where Self: UIViewController {
>        // Machinery to bridge to normal UIViewController API
>        
>        func performSegue(with identifier: SegueIdentifier, sender: AnyObject?) {...}
>        override func shouldPerformSegue(withIdentifier identifier: String, sender: AnyObject?) -> Bool {...}
>        override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {...}
>    }
> 
> Rather than attempting some sort of universal enum of all identifiers:
> 
>    extension UIViewController {
>        open enum SegueIdentifier: String {
>            // Extensible for users
>        }
>        
>        // Hooks
>        open func shouldPerformSegue(with identifier: SegueIdentifier, sender: AnyObject?) -> Bool {...}
>        open func prepare(for segue: UIStoryboardSegue, with identifier: SegueIdentifier, sender: AnyObject?) {...}
>        
>        // Machinery to bridge to normal UIViewController API
>        public func performSegue(with identifier: SegueIdentifier, sender: AnyObject?) {...}
>        override public func shouldPerformSegue(withIdentifier identifier: String, sender: AnyObject?) -> Bool {...}
>        override public func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {...}
>    }
> 
>> Then local extensions are free to define their own local enums to cover only their local extensions to the original core set of actions. Then the public api definition constrains the action parameter to be enum&TheRequiredInterface.
> 
> Okay, but why constrain it to `enum`? Do you actually care that it's an `enum`, or do you just care that there's a type which can give you the identifier you need? If somebody wrote a highly dynamic client of your code that needed to generate identifiers on the fly, why should your code reject that?

In the case of a segway id (i did watch the wwdc presentation last year too) the protocol representation is IMHO more a pedentic exercise in 'look how pretty i can make my code' than an actual technical necessity (considering people have been writing the same apps in objc for years, their argument of 'avoiding mismatch' did not hold much water when considering the scale we are talking about).

I was refering to real life systems (think state machine-like libraries for eg) where having access to the complete set carries a real value. For some, dealing with multiple disjointed sets is a minor hickup, for others a real feature. The point is i am describing carefully designed real life (many trading) systems for which i truly care about every piece of what i described for various reasons (be it size/modularity 400KLOC+ systems, bytecode level efficiency of enums as Hash keys, .... ). At this point none of these systems could be done in swift yet due to small gaps here and there (of course they could technically be rewritten in cobol if need be, but at a tremendous loss):
* can't constrain on enum (what's worse is Dave is not even convinced there is any case for it)
* can't easily discover all cases
* can't annotate enum case with meta information making runtime adaptation possible
...

Maybe the gap will never close and java/scala/kotlin/ceylon will remain the languages of choice for the real life servers of this world. An interesting question might be: what to do when a phonegap app written in typescript is much more expressive than its swift counterpart? Today i use swift because it is new and fun, but i find c# much more powerful for even iOS only apps. But i have high hopes.



More information about the swift-evolution mailing list