如何覆盖 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 要求添加到 Theme 协议中。 Swift 希望看到协议扩展中的默认实现。我想在实际的 LightTheme 实现中 'override' 它,但这不起作用。 属性 仍然是 returns 零。我该如何解决?
你做的是正确的,但如果你观察你的代码
let currentTheme: Theme.Type = LightTheme.self
currentTheme
是 Theme
的类型,但是您已经分配 LightTheme
现在是 Theme
并且在您的协议中
extension Theme {
static var feature: FeatureTheme.Type! {
return nil
}
}
您已将 nil
作为正在执行的默认实现返回,因为 currentTheme
是 Theme
类型不是 LightTheme
并且它也不需要正确
使用当前的实现解决方案也很简单,就是将 currentTheme
声明为 LightTheme
请参阅下面的答案
let currentTheme: LightTheme.Type = LightTheme.self
或
保持currentTheme
简单分配LightTheme
如下
let currentTheme = LightTheme.self
希望对您有所帮助
Output :
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
的扩展中定义了默认实现,也可以覆盖它。
我想以某种方式实现主题化,即功能可以将其所需的颜色添加到主题协议中,这样任何实际的主题实现都必须为每个功能提供颜色。我还希望将主题实现和功能主题要求放在单独的文件中。如果我将主题或功能移动到另一个项目中,我不想手动删除代码行。
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 要求添加到 Theme 协议中。 Swift 希望看到协议扩展中的默认实现。我想在实际的 LightTheme 实现中 'override' 它,但这不起作用。 属性 仍然是 returns 零。我该如何解决?
你做的是正确的,但如果你观察你的代码
let currentTheme: Theme.Type = LightTheme.self
currentTheme
是 Theme
的类型,但是您已经分配 LightTheme
现在是 Theme
并且在您的协议中
extension Theme {
static var feature: FeatureTheme.Type! {
return nil
}
}
您已将 nil
作为正在执行的默认实现返回,因为 currentTheme
是 Theme
类型不是 LightTheme
并且它也不需要正确
使用当前的实现解决方案也很简单,就是将 currentTheme
声明为 LightTheme
请参阅下面的答案
let currentTheme: LightTheme.Type = LightTheme.self
或
保持currentTheme
简单分配LightTheme
如下
let currentTheme = LightTheme.self
希望对您有所帮助
Output :
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
的扩展中定义了默认实现,也可以覆盖它。