2017-03-06 14 views
1

我對Swift很陌生,最近發現您不能從Swift中的泛型繼承,例如,替代繼承自Swift中的泛型參數

class MyClass<T> : T {} 

在Swift 3中無效(請參閱問題this question)。

這是我希望用上述構建來解決這個問題:

protocol Backend { 
    func operationA(operand: Int) 
} 

class ConcreteBackend : Backend { 

    func operationA(operand: Int) { 
    // ... 
    } 

    // Some other functions and/or custom initializers 
    // ... 
} 

class EnhancedBackend<T : Backend> : T { 

    override func operationA(operand: Int) { 
    // do something smart here 
    super.operationA(operand: modifiedOperand) 
    } 
} 

基本上EnhancedBackend不靈光一現用的operationA的輸入,然後把它傳遞給實際執行的Backend。 我在這裏使用繼承而不是組合,因爲ConcreteBackend可能有一些公共屬性,函數和初始值設定項沒有在協議中指定(因爲它們只與具體的實現有關),我還想用EnhancedBackend公開。 沒有繼承,這是不可能的。

A C++實現可能看起來像

// Using concepts here instead of protocols 
class ConrecteBackend { 
    public: 
    void operationA(int operand) { .... } 
} 

template<class T> 
class EnhancedBackend : public T { 
    using Base = T; 
    public: 
    // Ensure T is a model of the Backend concept 
    static_assert(isModelOfConceptBackend<T>::value, 
        "Template parameter is not a model of concept Backend"); 

    // Ensure all constructors of Base can be used 
    template<class ...Args, typename = std::enable_if_t< 
     std::is_constructible<Base, Args...>::value>> 
    inline EnhancedBackend(Args &&...args) : Base(std::forward<Args>(args)...) {} 

    void operationA(int operand) { 
     // ... 
     Base::operationA(operand); 
    } 
}; 
使用C

所以++這是相當簡單的解決這個問題。但目前我還不知道如何使用(純)Swift 3實現。

+0

你檢查出這個答案嗎? http://stackoverflow.com/questions/27508284/swift-inherit-from-generic-type?noredirect=1&lq=1 – Grimxn

+0

@Grimxn問答現場,但已經鏈接到OP上面的第一個代碼片段之後:) – dfri

+0

@dfri - 哎呀! :)只是讀到底部 - OP甚至評論這個問題! – Grimxn

回答

1

Swift的泛型與C++模板不同,它比Swift的類型語義更接近預處理宏。

然而,有許多方法可以實現類似的結果。如果一種方法使用變量引用需要定製的調度規則的功能:

例如:

protocol Backend:class 
{ 
    var operationA:(Int) ->() { get set } 

    func performOperationA(_ : Int) ->() 
} 

class ConcreteBackend : Backend 
{ 
    lazy var operationA:(Int) ->() = self.performOperationA 

    func performOperationA(_ : Int) ->() 
    { 
    // ... 
    } 

    // Some other functions and/or custom initializers 
    // ... 
} 

extension Backend 
{ 
    var enhancedForTesting:Self 
    { 
    operationA = testing_OperationA 
    return self 
    } 

    func testing_OperationA(_ operand:Int) ->() 
    { 
    let modifiedOperand = operand + 1 
    performOperationA(modifiedOperand) 
    } 

} 

let enhancedBackend = ConcreteBackend().enhancedForTesting 

通過使用一個變量來引用該函數的實現,就可以動態地改變運行a的行爲在運行時和特定實例。

在此示例中,增強功能被添加到後端協議,但它們也可能由獨立函數或甚至另一個具有其特定類型的改變行爲的類設置。

當使用這種方法時,實例具有具體類的所有屬性和功能,同時爲協議的改變的功能實現增強的行爲。

創建增強的實例使用一種語法,是一個通用類的構造函數一樣簡單(不超過簡單IF):

// for example: 

let instance = ConcreteBackend(...).enhanced 

// rather than: 

let instance = EnhancedBackend<ConcreteBackEnd>(...)