2017-04-22 1 views
0

Ich versuche ein einfaches Spiel mit Swift zu machen. Das Spiel hat verschiedene Levels und jedes Level erfordert, dass sich das Spiel auf unterschiedliche Weise verhält. Ich entschied mich, für jede Ebene eine andere Klasse zu verwenden, die alle von einer Basisklasse geerbt wurde.Optionale Funktionen zum Überschreiben in Swift-Klassen?

Dies ist die Basis:

import SpriteKit 

class LevelBase { 

    var scene: GameScene! // Seems very dodgy 
    var blocks = [SKSpriteNode]() 

    init(scene: GameScene) { // Should this be required init? 
    self.scene = scene 
    } 

    func filterBlock(_ block: SKSpriteNode) { 
    blocks = blocks.filter() { $0 !== block } // Looks really dodgy to me 
    } 

    func update(time: TimeInterval) { 
    // For override 
    } 

    func levelUp() { 
    // For override 
    } 

    func postGenerate() { 
    // For override 
    } 
} 

aber mir diese Klasse scheint geschrieben sehr schlecht werden. Ich kann nirgendwo Beispiele für Funktionen finden, die in einer Klasse erstellt wurden, nur um überschrieben zu werden, was mich denken lässt, dass ich etwas falsch mache. Sollte ich Erweiterungen oder Protokolle für optionale Funktionen wie diese verwenden? Ich verstehe nicht ganz, wie sie funktionieren, also habe ich bisher noch keine benutzt.

Das zweite Problem ist, dass diese Klasse mit der Spielszene Variable initialisiert werden muss, da einige Ebene sie brauchen Sprites hinzuzufügen oder zu entfernen. Dies scheint besonders zweifelhaft, wenn man bedenkt, dass die Klasse in der Datei der Spielszene erstellt wurde.

Sicherlich gibt es einen besseren Weg?

+0

erstellt werden Sie gemeinsame Funktionalität Protokolle extrahieren könnten die Methoden Standardimplementierungen in einer Erweiterung angegeben. Conforming-Typen können dieses Standardverhalten verwenden oder es selbst implementieren – Alexander

+0

Ich hätte lieber eine (letzte) Level-Klasse, die ich mit einem Objekt instanziieren kann, das die fragliche Methode hat. – vikingosegundo

+0

https://en.wikipedia.org/wiki/Composition_over_inheritance – vikingosegundo

Antwort

3

Ich habe keine Erfahrung mit SpriteKit, sondern aus einer allgemeinen Perspektive sollten Sie zu "Favour composition over Inheritance" betrachten.

Sie würden eine Stufe Klasse, die nicht für die Unterklassen gedacht, sondern kann mit Objekten oder Werten instanziert werden, die unterschiedliche Umsetzung haben.

Zusätzlich sollten Sie Protokolle verwenden, um diejenigen zu definieren und Sie können Standardimplementierung als Protokollerweiterungen hinzuzufügen.

final class Level { 
    init(levelImplementation: LevelImplementationType) { 
     self.levelImplementation = levelImplementation 
    } 

    let levelImplementation: LevelImplementationType 

    func navigate() { 
     levelImplementation.navigate() 
    } 

    func update(timeInterval: TimeInterval) { 
     levelImplementation.update(timeInterval: timeInterval) 
    } 

} 

Die Ebene würde mit einem Objekt oder Struktur konform LevelImplementationType

protocol LevelImplementationType { 
    func navigate() 
    func update(timeInterval: TimeInterval) 
} 

Standardimplementierungen instanziiert werden kann über eine Verlängerung erfolgen.

extension LevelImplementationType { 
    func navigate() { 

    } 
    func update(timeInterval: TimeInterval) { 

    } 
} 

Die LevelImpelmenation muss LevelImplementationType, entsprechen aber haben keine weiteren Einschränkungen. d.h. sie können sehr unterschiedliche Initialisierer haben.

struct LevelImplementation1: LevelImplementationType { 
    // useses default implementation of `navigate` and `update` from extension 
} 

struct LevelImplementation2: LevelImplementationType { 
    // useses default implementation of `update` from extension 

    func navigate() { 
    } 
} 

struct LevelFileImplementation: LevelImplementationType { 
    init(with path: String) { 
     // read variables from file at path 
    } 

    func navigate() { 
     // navigate as given in file 
    } 

} 

Ebene Instanzen Rohr wie

let level1 = Level(levelImplementation: LevelImplementation1()) 
let level2 = Level(levelImplementation: LevelImplementation2()) 
let level3 = Level(levelImplementation: LevelFileImplementation(with: "path/to/file")) 
+0

Auch, sorry für diese dumme Frage, aber warum ist die Ebene Basis eine Klasse, wenn die Implementierungen Strukturen sind? – MysteryPancake

+0

Wenn ich versuche, Standardwerte für das Protokoll mit einer Erweiterung zu definieren, wie soll ich dann filterBlock definieren? Die Blöcke Tabelle existiert nicht in der Verlängerung, nur in der Basisebene Datei, so kann ich nicht darauf zugreifen: 'Verlängerung LevelImplementation { func Filterblock (_ Block: SKSpriteNode) { badblocks = badBlocks.filter() {$ 0 ! == block} dedicatedBlocks = selectedBlocks.filter() {$ 0! == Block} } } 'Funktioniert nicht – MysteryPancake

+0

Ich denke, ich werde einen neuen Thread beginnen – MysteryPancake

Verwandte Themen