【问题标题】:Return object of concrete class that implements a protocol返回实现协议的具体类的对象
【发布时间】:2016-02-04 16:35:41
【问题描述】:

我遇到了这个我无法解决的问题,也没有找到太多相关信息。

我的情况是,我想从工厂函数返回一个UIViewController 实例,它也实现了一个协议,我们称之为Protocol。我想知道是否有人遇到过这种情况并找到任何解决方案?

在 Objective-C 中它看起来像这样:

- (UIViewController<Protocol>*)createControllerForIdentifier:(NSString*)identifier

有没有 Swift 的方法来写这个?

Protocol 限制为具体类或子类对我来说是可以的。

我找到了this thread,但无法转换为我的案例

感谢您的帮助。

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    根据具体情况,有多种选择。这是一种可能会有所帮助的通用方法。但是,我建议重写代码,所以这不是一个真正的问题。 Swift 和 Objective-C 是不同的语言,一些设计模式根本不(并且可能永远不会)在这两种语言中都可用。在这种情况下,移植代码需要从头开始重新考虑代码。

    您可以通过引入如下绑定协议来实现安全性和便利性:

    // protocol you want to implement
    // this may possibly be implemented by other types besides our Base (no restrictions)
    protocol P1 {
        func run()
    }
    
    
    // base class of objects to instantiate
    class Base {
        // Base specific method
        func display() {
            print("Displaying...")
        }
    }
    
    
    // wrapper to get both P1 and Base
    // our special protocol will be dedicated to P1 and Base
    protocol PB : P1 {      // already a P1
        // property to safely get this instance as a Base without casting
        var asBase : Base { get }
    }
    
    
    // extension to safely implement the binding for P1 and Base
    // anything we implement in this extension is safe for both P1 and Base
    extension PB where Self : Base {
        var asBase : Base { return self }
    }
    
    
    // concrete subclass of Base which also implements PB and hence P1
    class X : Base, PB {
        // implement protocol
        func run() {
            print("Running...")
        }
    }
    
    
    // factory function to make a concrete instance of Base implementing P1
    func makePB() -> PB {
        return X()
    }
    
    
    let pb = makePB()
    pb.run()                // directly access as P1
    pb.asBase.display()     // both safe and easy to access as Base
    

    【讨论】:

      【解决方案2】:

      斯威夫特 4 ❤️

      func createController(for identifier: String) -&gt; (UIViewController &amp; Protocol)

      【讨论】:

        【解决方案3】:

        一种方法如下:

        protocol Protocol {
            func bar()
        }
        
        class MyViewController : UIViewController, Protocol {
        
            func bar() {
                print("Bar")
            }
        
            static func getInstance() -> MyViewController {
                return self.init()
            }
        
        }
        
        /* Example usage */
        let foo = MyViewController.getInstance() 
        print(foo.dynamicType) // MyViewController
        foo.bar() // Bar
        
        /* Naturally works to pass foo to 'Protocol' type constrained function */
        func foobar<T: Protocol>(fizz: T) {
            fizz.bar()
        }
        foobar(foo) // bar
        

        或者,对于更通用/可重用的方法(具有简单 init() 初始化程序的类/结构的工厂方法):

        /* Setup generic factory */
        protocol FactoryInitializers {
            init()
        }
        
        protocol FactoryMethods {
            typealias T: FactoryInitializers
        }
        extension FactoryMethods {
            static func getInstance() -> T {
                return T()
            }
        }
        
        protocol Factory : FactoryMethods, FactoryInitializers { }
        
        /* Apply for your example, with conformance to 'Factory' (to get access 
           to default implementation 'getInstance' method) as well as a custom 
           protocol 'Protocol'              */
        protocol Protocol {
            func bar()
        }
        
        class MyViewController : UIViewController, Factory, Protocol {
            typealias T = MyViewController
        
            func bar() {
                print("Bar")
            }
        }
        

        与上面简单版本的结果相同:

        let foo = MyViewController.getInstance() // OK, MyViewController conforms to Factory
        print(foo.dynamicType) // MyViewController
        foo.bar() // Bar
        
        /* Naturally works to pass foo to 'Protocol' type constrained function */
        func foobar<T: Protocol>(fizz: T) {
            fizz.bar()
        }
        foobar(foo) // bar
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-05
          • 1970-01-01
          • 2022-11-27
          相关资源
          最近更新 更多