> On Jul 2, 2016, at 12:42 AM, L. Mihalkovic <[email protected]> 
> 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?

-- 
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to