2017-08-26 82 views
3

在我的應用我讀類型EKEvent的日曆事件,我已經做了很多計算瓦爾的擴展,這樣我就可以輕鬆搞定的持續時間,工時數等,在日曆中的每個事件。但在大規模情況下,性能很差 - 所以我想使用懶惰變量來緩存所有額外的數據。如何用它的超類的實例啓動我的子類?

因此,我想創建EKEvent的一個子類 - 稱爲CustomEvent,它添加了懶惰的變量,但是我的問題是EKEventStore總是返回EKEvents,我需要將它轉換爲我的CustomEvent子類的實例,按順序要能夠訪問懶瓦爾等

一個簡單的類型轉換是不夠的,我試過在一個操場上,看看有什麼可以工作,但什麼也沒得到有用。我需要一個CustomRectangle的特殊構造函數,它可以從NativeRectangle初始化一個CustomRectangle。另一種解決方案是使持有原來的對象作爲屬性的包裝類,但是這不會是我最喜歡的解決方案,因爲我接下來要映射所有的方法和屬性

class NativeRectangle: NSObject { 
    var width: Int 
    var height: Int 

    init(width: Int, height: Int) { 
     self.width = width 
     self.height = height 
     super.init() 
    } 
} 

class CustomRectangle: NativeRectangle { 
    var area: Int { return width * height} 
} 

let rect = NativeRectangle(width: 100, height: 20) 

let customRect = CustomRectangle(rect) // This fails, i need a constructor 

print(customRect.area) 

回答

0

如果你已經在Objective-C的土地工作,有包裝的原生類,並自動將所有(除加)消息的選項:

- (NSMethodSignature*) methodSignatureForSelector: (SEL) selector 
{ 
    NSMethodSignature *ours = [super methodSignatureForSelector:selector]; 
    return ours ?: [wrappedObject methodSignatureForSelector:selector]; 
} 

我不記得,如果這是需要的轉發一切工作,但它應該非常接近。另外,我不知道如何做到這一點與斯威夫特玩,所以我想我們可以考慮從這個Objective-C的天一個有趣的瑣事,並尋找一個更好的解決方案...


第二個,也想到的稍微黑客的選項是使用associated objects feature將緩存的數據鏈接到原始實例。這樣你可以保持你的擴展方法。

3

有斯威夫特沒有辦法(和一般的大多數面向對象的語言)創建一個子類的實例時使用一個基類對象的現有實例。

從一般的編程待命點你在這種情況下兩個選擇:

  1. 使用組成:使CustomRectangle包含NativeRectangle和轉發,你需要的所有方法吧。

  2. 使用地圖NativeRectangles鏈接到的其他信息。在Objective C和Swift中,您可以通過objc_AssociationPolicy輕鬆獲得這樣的內部映射。見https://stackoverflow.com/a/43056053/278842

Btw。從「緩存」一個簡單的計算,您將無法看到任何加速,如width * height

+0

構圖通常是我不得不這樣做時想到的第一個想法。 – Abizern

+0

謝謝 - 當我不得不做一個包裝類和映射屬性時,我想......我希望有一個更優雅的解決方案。寬度*高度的簡單「緩存」就是這個例子...... –

0

您創建了自己的CustomRectangle(object: rect),因此swift不會再提供默認的init()。你明確需要打電話給你自己的一個持有你的財產,並致電super.init(),因爲你的課程也從超類繼承。 -

class NativeRectangle: NSObject { 
    var width: Int 
    var height: Int 

    // Super class custom init() 
    init(width: Int, height: Int) { 
     self.width = width 
     self.height = height 
     super.init() 
    } 
} 

class CustomRectangle: NativeRectangle { 

    // computed property area 
    var area: Int { return width * height} 

    // Sub class Custom Init 
    init(object:NativeRectangle) { 
     // call to super to check proper initialization 
     super.init(width: object.width, height: object.height) 
    } 
} 

let rect = NativeRectangle(width: 100, height: 20) 

let customRect = CustomRectangle(object: rect) 

print(customRect.area) //2000 
+0

我不認爲這是EKEvents的解決方案,因爲它們沒有適當的構造函數可用。但對於其他類型,它可能是有用的。我會堅持@Christopher Oezbek的建議 –

+0

@Esben von Buchwald對EKEvents或初始化的工作原理沒有太多的瞭解。但是上面的答案是基本的初始化過程,在swift或其他任何語言中很可能都遵循。事實上,你可以堅持使用Oezbek解決方案。 –

相關問題