2015-06-13 194 views
3

我有一個靜態屬性的類,我想訪問特定的對象。代碼如下:從對象讀取靜態屬性

import UIKit 

protocol Theme { 
    static var name: String { get } 

    func getBackgroundColor() -> UIColor 
} 

class DefaultTheme: Theme { 
    static var name = "Default theme" 

    func getBackgroundColor() -> UIColor { 
     return UIColor.blackColor() 
    } 
} 

var currentTheme: Theme = DefaultTheme() 
println(currentTheme.name) //Error: 'Theme' does not have a member named 'name' 

無法通過DefaultTheme.name因爲currentTheme可能是一個不同的主題類的實例存取權限主題的名字,但我需要知道它的名字。我怎樣才能訪問這個靜態變量?

我使用的Xcode 6.3.1(斯威夫特與1.2)

回答

4

你已經打了一個不起眼的和非常有趣的bug雨燕1.2。 Swift與協議所需的靜態變量有關的錯誤歷史悠久,而且這似乎是另一種。

顯然,這裏的問題在於您試圖將基於協議的特徵與基於類的特徵混合匹配。假設你曾這樣說:

var currentTheme = DefaultTheme() 

然後currentTheme將被類型化爲DefaultTheme - 一個類的實例。這意味着您可以從例如通過將直通該實例的dynamicType訪問類成員:

println(currentTheme.dynamicType.name) // "Default theme" 

但你不能這樣做,在你的代碼,因爲你已經輸入currentTheme作爲一個主題 - 一個協議:

var currentTheme : Theme = DefaultTheme() 

這並不奇怪的事情到name財產,這是由協議規定,所以你不能在所有訪問name財產的概念。

如果主題爲DefaultTheme的超類,則不會出現此問題。在這種情況下,你可以使用一個類屬性(它必須是一個計算屬性),它將以多態的方式工作。在雨燕1.2,這可能是你最好的選擇:

class Theme { 
    class var name : String { return "Theme" } 
} 
class DefaultTheme: Theme { 
    override class var name : String { return "Default theme" } 
} 
var currentTheme : Theme = DefaultTheme() 
println(currentTheme.dynamicType.name) // "Default theme" 

在另一方面,當你升級到斯威夫特2,你會發現,這個錯誤是固定的,所以print(currentTheme.dynamicType.name)作品完美即使有協議:

protocol Theme { 
    static var name : String { get } 
} 
class DefaultTheme: Theme { 
    static var name = "Default theme" 
} 
var currentTheme : Theme = DefaultTheme() 
print(currentTheme.dynamicType.name) // "Default theme"