簡體   English   中英

如何在Swift中覆蓋協議擴展的計算屬性

[英]How to override computed property of protocol extension in Swift

我想以某種方式實現主題化,即功能可以將其所需的顏色添加到主題協議中,以便任何實際的主題實現都必須為每個功能提供顏色。 我還希望在單獨的文件中具有主題實現和功能主題要求。 如果將主題或功能部件移動到另一個項目中,我不想手動刪除代碼行。

import UIKit

protocol Theme {
    static var genericColor: UIColor { get }
}

protocol FeatureTheme {
    static var featureColor: UIColor { get }
}

extension Theme {
    static var feature: FeatureTheme.Type! {
        return nil
    }
}

struct LightTheme: Theme {
    static var genericColor: UIColor { return .white }

    static var feature: FeatureTheme.Type! { return Feature.self }
    struct Feature: FeatureTheme {
        static var featureColor: UIColor { return UIColor.red }
    }
}

let currentTheme: Theme.Type = LightTheme.self

print(currentTheme) // LightTheme
print(currentTheme.feature.featureColor) // error, because feature is nil

因此,我想通過擴展將FeatureTheme需求添加到主題協議中。 Swift希望在協議擴展中看到默認的實現。 我想在實際的LightTheme實現中“覆蓋”它,但這不起作用。 該屬性仍然返回nil。 我該如何解決?

您所做的是正確的,但是如果您遵守自己的代碼

let currentTheme: Theme.Type = LightTheme.self

currentThemeTheme類型,但是您已將LightTheme分配為Theme並且已在您的協議中

extension Theme {
    static var feature: FeatureTheme.Type! {
        return nil
    }
}

您已返回nil作為正在執行的默認實現,因為currentThemeTheme類型而不是LightTheme ,並且也沒有正確要求

使用當前實現,解決方案很簡單,就是將currentTheme聲明為LightTheme參見以下答案

let currentTheme: LightTheme.Type = LightTheme.self

要么

保持currentTheme即可像下面那樣簡單分配LightTheme

let currentTheme  = LightTheme.self

希望對您有幫助

輸出:

LightTheme UIExtendedSRGBColorSpace 1 0 0 1

Theme的擴展不會對協議添加任何要求,它只是將計算出的靜態屬性添加到Theme.Type類型的任何內容中。 因此,對於任何Theme.Type ,您都不會覆蓋feature的默認實現。 只有feature是協議的實際要求時,情況才會如此。 也許是這樣的:

protocol Theme {
    static var feature: FeatureTheme.Type { get }
    static var genericColor: UIColor { get }
}

protocol FeatureTheme {
    static var featureColor: UIColor { get }
}

struct LightTheme: Theme {
    static var genericColor: UIColor { return .white }

    static var feature: FeatureTheme.Type { return Feature.self }
    struct Feature: FeatureTheme {
        static var featureColor: UIColor { return UIColor.red }
    }
}

let currentTheme: Theme.Type = LightTheme.self

print(currentTheme) // "LightTheme"
print(currentTheme.feature.featureColor) // "UIExtendedSRGBColorSpace 1 0 0 1"

然后,也就不需要feature是可選的並強制展開。

很抱歉在評論中有誤解。
這是兩個解決方案:
1.這是@Prashant Tukadiya的答案。 currentTheme聲明為LightTheme
2.但是,我認為由於某種原因,您必須將其設置為Theme.type 因此,將feature聲明為Theme協議的屬性,可以(應該)將其重寫。

protocol Theme {
    static var genericColor: UIColor { get }
    static var feature: FeatureTheme.Type! { get }
}

如果您不這樣做,則Theme.feature的定義只是Theme的靜態屬性。 然后LightTheme.feature不會從Theme繼承。 如果這樣做, Theme.feature可以(應該)在子類中實現Theme.feature 您在Theme的擴展中定義了默認實現,也可以覆蓋它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM