2017-08-14 69 views
0

在斯威夫特,你不能在協議定義本身定義的功能或屬性的默認實現,即:爲什麼必須通過Swift中的擴展實現協議默認值?

protocol Container { 
    //These are fine 
    associatedtype Item 
    mutating func append(_ item: Item) 
    var count: Int { get set } 
    subscript(i: Int) -> Item { get } 

    //These are not fine 
    var defaultValue: Int = 10 
    mutating func messWithCount(){ 
     self.count *= 10 
    } 
}  

extension Container { 
    //This is fine though 
    mutating func messWithCount(){ 
     self.count *= 10 
    } 
} 

但是你可以通過擴展這樣做(儘管擴展不支持存儲性能,它們支持的功能和計算的 - 雖然存儲的財產問題可以是worked around)。

這背後的解釋是什麼?作爲補充,optional func的解釋只有在我們將Protocol和func都標記爲@objc並因此使其不可用於Structs/Enums(基於Value而不是基於引用)時纔可實現?

編輯:添加在擴展示例

+1

有沒有真正的理由在協議聲明的默認實現AREN不可能;差別僅僅是語法。因此,我認爲這不是執行的重中之重(如果有的話)。它[包含在泛型聲明中](https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#default-implementations-in-protocols-),所以可能會被認爲是該語言的更高版本。 – Hamish

回答

0

@optional指令是一個Objective-C僅指示並沒有被翻譯成斯威夫特。這並不意味着你不能在Swift中使用它,但是你必須首先使用@objc屬性將Swift代碼暴露給Objective-C。

請注意,暴露給Obj-C只會使協議可用於Swift和Obj-C中的類型,這不包括例如Structs,因爲它們只在Swift中可用!

要回答你的第一個問題,協議在這裏定義和沒有實現:

協議定義的方法,屬性,和其它要求的藍圖[...]

而且因此實現應該由符合它的類/ stuct/enum提供:

然後協議可以被類,結構或枚舉採用來提供n實際執行這些要求

這個定義確實適用於我們在日常生活中使用的協議。舉個例子的協議寫一個文件:

PaperProtocol限定了紙爲具有以下非零變量的文檔:

  • 簡介
  • 章節
  • 結論

引言,章節和結論包含的內容取決於實現它們的人(作者)而不是protoco湖

當我們在擴展的定義,我們可以看到,他們來這裏是爲了增加(實施)的新功能:

擴展添加新的功能,以現有的類,結構,枚舉,或協議類型。這包括擴展您無法訪問原始源代碼的類型的功能。

因此,擴展一個協議(這是允許的)給你添加新功能的可能性,並在此給出一個定義方法的默認實現。這樣做可以作爲Swift替代上面討論的@optional指令。

UPDATE:

雖然給人一種默認實現在交換機的協議功能確實使「可選」,它是根本不一樣的Objective-C中使用@optional指令。

在Objective-C中,未實現的可選方法根本沒有實現,因此調用它會導致崩潰,因爲它不存在。因此,必須在調用它之前檢查它是否存在,與Swift相反,使用擴展缺省值,因爲缺省實現存在時可以安全地調用它。

中的OBJ-C可選會這樣使用:

NSString *thisSegmentTitle; 
// Verify that the optional method has been implemented 
if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) { 
    // Call it 
    thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index]; 
} else { 
    // Do something as fallback 
} 

凡的SWIFT對應與擴展默認是:

let thisSegmentTitle = self.dataSource.titleForSegmentAtIndex(index) 
+0

所以這個現象是由Swift(因此Chris Lattner)如何定義協議和擴展,而不是一些隱藏的實現細節帶來的? Swift的文檔確實強調了擴展默認v @optional是不一樣的 - (通過擴展提供的默認實現的協議要求不同於可選的協議要求)。我個人覺得不得不延長這樣的事情有點笨重,也許是因爲我太習慣Java的界面風格了 – Mercato

+0

@Mercato我更新了我的答案,可選和擴展默認的主要區別在於它太長了評論! – Thomas

相關問題