2014-10-20 71 views
5

我目前正在編寫一些主要是Objective-C的項目中的Swift代碼。在我們的ObjC代碼中,我們有一個標題,聲明typedef GPUImageOutput<GPUImageInput> MyFilter;。然後我們可以聲明例如@屬性只能是GPUImageOutput子類,它實現了GPUImageInput什麼是聲明`typedef SomeClass <SomeProtocol> MyType`的Swift等價物?

(注:GPUImageOutputGPUImageInput不是由我定義的;它們是GPUImage library的一部分)

我們的銀行代碼似乎並沒有認識到這一點,即使頭在我們的橋接報#imported。我試圖複製在斯威夫特的聲明,但這些都不是正確的語法:
typealias MyFilter = GPUImageOutput, GPUImageInput
typealias MyFilter = GPUImageOutput : GPUImageInput

+2

我問同樣的事情在這裏:http://stackoverflow.com/questions/24455327/how-do-i-specify-that-a-non-generic-swift-type-should-遵守協議,出於同樣的原因。 – 2014-10-21 16:57:05

回答

2

在斯威夫特4您可以用新的&標誌實現這一目標(以下參數的一個例子,確認到的UIViewController和UITableViewDataSource:

func foo(vc: UIViewController & UITableViewDataSource) { 
    // access UIViewController property 
    let view = vc.view 
    // call UITableViewDataSource method 
    let sections = vc.numberOfSectionsInTableView?(tableView) 
} 
1

在斯威夫特,類似下面應該完成你的任務,但它比它的ObjC對應不同:

typealias GPUImageOutput = UIImage 
@objc protocol GPUImageInput { 
    func lotsOfInput() 
} 

class GPUImageOutputWithInput: GPUImageOutput, GPUImageInput 
{ 
    func lotsOfInput() { 
     println("lotsOfInput") 
    } 
} 

// ... 

var someGpuImage = GPUImageOutput() 
var specificGpuImage = GPUImageOutputWithInput() 

for image in [someGpuImage, specificGpuImage] { 
    if let specificImage = image as? GPUImageInput { 
     specificImage.lotsOfInput() 
    } else { 
     println("the less specific type") 
    } 
} 

更新:現在我明白的地方/你爲什麼有這些類型的...

GPUImage似乎有一個快速的例子,你想要做什麼,斯威夫特-LY越好。

here

class FilterOperation<FilterClass: GPUImageOutput where FilterClass: GPUImageInput>: FilterOperationInterface { 
... 

type constraint syntax可以應用到的功能,也和一個where clause,這可能是一樣好,你會直接在斯威夫特得到。

我越試圖瞭解如何移植這個有點常見的objc變形,我越發現它是最迅速的方式。一旦我在GPUImage本身中看到了示例,我確信這至少是您的答案。 :-)

更新2:因此,除了上面鏈接到使用Swift的特定GPUImage示例,我越來越多地考慮使用where子句來保護setter函數或使用可計算屬性過濾set功能似乎是唯一的出路。

我想出了這樣的策略:

import Foundation 

@objc protocol SpecialProtocol { 
    func special() 
} 

class MyClass {} 

class MyClassPlus: MyClass, SpecialProtocol { 
    func special() { 
     println("I'm special") 
    } 
} 

class MyContainer { 
    private var i: MyClass? 

    var test: MyClass? { 
     get { 
      return self.i 
     } 
     set (newValue) { 
      if newValue is SpecialProtocol { 
       self.i = newValue 
      } 
     } 
    } 
} 

var container = MyContainer() 

println("should be nil: \(container.test)") 

container.test = MyClass() 
println("should still be nil: \(container.test)") 

container.test = MyClassPlus() 
println("should be set: \(container.test)") 

(container.test as? MyClassPlus)?.special() 

輸出:

should be nil: nil 
should still be nil: nil 
should be set: Optional(main.MyClassPlus) 
I'm special 

(或者,您也可以在地方is支票的使用precondition(newValue is SpecialProtocol, "newValue did not conform to SpecialProtocol"),但會像一個assert()可以如果沒有滿足的情況下崩潰的應用程序。取決於您的需求。)

@ rintaro的答案是一個很好的例子,是一個很好的例子where子句作爲後衛(包括功能性很強和Swift-ly)。然而,我只是討厭在可計算屬性存在時編寫一個setFoo()函數。然後,即使使用可計算屬性也有代碼異味,因爲我們似乎無法將通用類型約束應用於set,因此必須在線執行協議一致性測試。

+0

對不起,b ut' GPUImageOutput'和'GPUImageInput' [預先存在](https://github.com/BradLarson/GPUImage),所以我不能只是重新聲明它們。將更新我的問題澄清! – 2014-10-20 22:23:09

+0

這只是一個例子,因爲我不知道你的基類是什麼!關鍵是@objc協議,它可以讓你檢測一致性。 – greymouser 2014-10-21 01:12:25

+0

...還有+1的問題 - 這是Swift訴ObjC差異的一個非常有趣的案例。 – greymouser 2014-10-21 01:27:10

4

你不能像這樣聲明typealias。

我們能做的最好的是這樣的:

class MyClass { 
    private var filter:GPUImageOutput 

    init<FilterType:GPUImageOutput where FilterType:GPUImageInput>(filter:FilterType) { 
     self.filter = filter 
    } 

    func setFilter<FilterType:GPUImageOutput where FilterType:GPUImageInput>(filter:FilterType) { 
     self.filter = filter 
    } 

    func someMethod() { 
     let output = self.filter 
     let input = self.filter as GPUImageInput 
     output.someOutputMethod() 
     input.someInputMethod() 
    } 
} 
+0

不錯!是的,這裏是一個類似的答案重複的問題:http://stackoverflow.com/a/24455591/418982 – 2014-10-24 21:56:17

-3

可以使用typealias關鍵字。下面是如何做到這一點:

typealias MyNewType = MyExistingType 

無論MyExistingType是協議還是函數還是枚舉都無關緊要。所有它需要是某種類型。最好的部分是您可以對其應用訪問控制。你可以說

private typealias MyNewType = MyExistingType 

這使得MyNewType才能訪問是在定義的上下文。

+0

這個問題是特別要求如何聲明一個實現該協議的類的對象的類型別名,而不只是一個或另一個。 – 2014-10-20 22:18:40

相關問題