2016-02-04 68 views
2

我遇到了這個問題,我無法解決,也沒有發現太多。實現協議的具體類的返回對象

我的情況是,從工廠函數我想返回一個UIViewController實例,它也實現了一個協議,我們稱之爲Protocol。我想知道是否有人經歷過這個並找到了解決方案?

在Objective-C就應該是這樣的:

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

有沒有寫這個任何斯威夫特方式?

將具體類或子類限制爲Protocol對我的情況可以。

我發現this thread但無法轉換到我的情況

感謝您的幫助。

回答

1

夫特4❤️

func createController(for identifier: String) -> (UIViewController & Protocol)

0

的一種方法如下:

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 
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 
相關問題