2016-06-22 21 views
12

Da statische gespeicherte Eigenschaften (noch) nicht für generische Typen in swift unterstützt werden, frage ich mich, was eine gute Alternative ist.Was ist eine gute Alternative für statische gespeicherte Eigenschaften von generischen Typen in swift?

Mein spezifischer Anwendungsfall ist, dass ich ein ORM in schnellen aufbauen will. Ich habe ein Entity Protokoll, das einen verbundenen Typ für den Primärschlüssel hat, da einige Entitäten eine Ganzzahl als id haben und einige eine Zeichenkette etc. haben. So macht das Entity Protokoll generisch.

Jetzt habe ich auch eine EntityCollection<T: Entity> Art, die Sammlungen von Unternehmen verwaltet und wie Sie es auch generic sehen können. Das Ziel von EntityCollection ist, dass Sie Auflistungen von Entitäten so verwenden können, als wären sie normale Arrays, ohne dass Sie wissen müssen, dass dahinter eine Datenbank liegt. EntityCollection kümmert sich um Abfragen und Caching und wird so optimiert wie möglich.

Ich wollte statische Eigenschaften auf dem EntityCollection verwenden, um alle Entitäten zu speichern, die bereits aus der Datenbank abgerufen wurden. Wenn also zwei separate Instanzen von EntityCollection dieselbe Entität aus der Datenbank abrufen möchten, wird die Datenbank nur einmal abgefragt.

Haben Sie Jungs eine Ahnung, wie ich sonst das erreichen könnte?

Antwort

0

Alles, was ich kann kommen mit ist der Begriff der Quelle zu trennen (wo die Sammlung herkommt) und dann Sammlung selbst. Und dann ist die Quelle verantwortlich für das Caching. An diesem Punkt kann die Quelle tatsächlich eine Instanz sein, so dass sie alle gewünschten Caches behalten kann und Ihre EntityCollection nur für die Pflege eines CollectionType- und/oder SequenceType-Protokolls um die Quelle verantwortlich ist.

Etwas wie:

protocol Entity { 
    associatedtype IdType : Comparable 
    var id : IdType { get } 
} 

protocol Source { 
    associatedtype EntityType : Entity 

    func first() -> [EntityType]? 
    func next(_: EntityType) -> [EntityType]? 
} 

class WebEntityGenerator <EntityType:Entity, SourceType:Source where EntityType == SourceType.EntityType> : GeneratorType { ... } 

Klasse WebEntityCollection: SequenceType {...}

funktionieren würde, wenn Sie einen typischen ausgelagerten Web-Daten-Schnittstelle. Dann könntest du etwas in der Art von:

class WebQuerySource<EntityType:Entity> : Source { 
    var cache : [EntityType] 

    ... 

    func query(query:String) -> WebEntityCollection { 
     ... 
    } 
} 

let source = WebQuerySource<MyEntityType>(some base url) 

for result in source.query(some query argument) { 
} 

source.query(some query argument) 
     .map { ... } 
     .filter { ... } 
0

Etwas wie das tun?

protocol Entity { 

} 

class EntityCollection { 
    static var cachedResults = [Entity]() 

    func findById(id: Int) -> Entity? { 
     // Search cache for entity with id from table 

     // Return result if exists else... 

     // Query database 

     // If entry exists in the database append it to the cache and return it else... 

     // Return nil 
    } 
} 
+3

Das ist nicht für mich arbeiten, da ich mit generischem Typ arbeiten bin und diese Typen nicht zulassen statisch gespeicherten Eigenschaften. Das ist genau, warum ich diese Frage poste ... – Evert

+0

Vielleicht können Sie Cache ändern, eine globale Variable vom Typ [AnyObject] und innerhalb der EntityCollection-Methoden, die zu [T] gegossen werden? – mikem

5

Ich bin nicht sicher, ob ich das noch mag oder nicht, aber ich habe eine statische berechnete Eigenschaft:

private extension Array where Element: String { 
    static var allIdentifiers: [String] { 
     get { 
      return ["String 1", "String 2"] 
     } 
    } 
} 

Gedanken?

+1

Dies scheint die Swifty-Lösung zu sein. Ich wünschte wirklich, sie würden uns gespeicherte Konstanten verwenden lassen. :/ –

+2

Ich denke, das würde kompilieren, aber jedes Mal eine neue Kopie erstellen und sich wie eine nicht statische Eigenschaft verhalten. – pshah

2

Vor einer Stunde habe ich ein Problem fast wie Ihres. Ich möchte auch eine BaseService-Klasse und viele andere Dienste, die von dieser geerbt werden, mit nur einer statischen Instanz. Und das Problem ist, alle Dienste nutzen ihr eigenes Modell (zB: Userservice UserModel mit ..)

Kurz gesagt habe ich versucht, Code folgen. Und es funktioniert!.

class BaseService<Model> where Model:BaseModel { 
    var models:[Model]?; 
} 

class UserService : BaseService<User> { 
    static let shared = UserService(); 

    private init() {} 
} 

Ich hoffe, es hilft.

Ich denke, der Trick BaseService war, wird es nicht direkt so dass keine Notwendigkeit verwendet werden, um statische gespeicherte Eigenschaft zu haben. (P.S.Ich wünsche swift unterstützt abstrakte Klasse, BaseService sollte)

+0

Was für ein Zufall! Ich habe das Problem mit dieser Lösung und dann sehe ich deine Antwort! : D – nahung89

0

Es stellt sich heraus, dass, obwohl Eigenschaften nicht erlaubt sind, Methoden und berechneten Eigenschaften sind. So können Sie etwas tun:

class MyClass<T> { 
    static func myValue() -> String { return "MyValue" } 
} 

Oder:

class MyClass<T> { 
    static var myValue: String { return "MyValue" } 
} 
Verwandte Themen