2017-04-22 12 views
0

私はSwiftを使って簡単なゲームを作ろうとしています。ゲームはさまざまなレベルを持ち、それぞれのレベルではゲームが若干異なる振る舞いをする必要があります。基本レベルのクラスから継承された、それぞれのレベルに異なるクラスを使用することに決めました。Swiftクラスのオーバーライドのオプション機能?

これがベースです:

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 
    } 
} 

しかし、私には、このクラスは非常にひどく書かれたと思われます。私は、クラス内で作成された関数をどこにも上書きすることができないので、何か間違っていると思います。私はそのようなオプションの機能に拡張機能やプロトコルを使用すべきですか?どのように動作するのか分かりませんので、これまで使用していません。

第二の問題は、いくつかのレベルが、それはスプライトを追加または削除する必要があるため、このクラスは、ゲームシーンの変数で初期化する必要があるということです。これは、ゲームシーンのファイルにクラスが作成されていることを考慮すると、特に厄介なようです。

確かに良い方法がありますか?

+0

のように作成すること。準拠型はこのデフォルトの振る舞いを使用するか、それ自体を実装することができます – Alexander

+0

私はむしろ問題のメソッドを持つオブジェクトをインスタンス化できる(最終的な)レベルのクラスを持っています。 – vikingosegundo

+0

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

答えて

3

私はSpriteKitベースでの経験がないが、一般的な観点からあなたは"Favour composition over Inheritance"に検討すべきです。

あなたはサブクラス化するためのものではなく、異なる実装を持つオブジェクトまたは値でインスタンス化することができるものLevelクラスを持っているでしょう。

また、あなたはそれらを定義するためのプロトコルを使用する必要がありますし、プロトコルの拡張として、デフォルトの実装を追加することができます。

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

    let levelImplementation: LevelImplementationType 

    func navigate() { 
     levelImplementation.navigate() 
    } 

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

} 

レベル適合

protocol LevelImplementationType { 
    func navigate() 
    func update(timeInterval: TimeInterval) 
} 
LevelImplementationTypeにデフォルト実装は拡張を介して行うことができる物体または構造体でインスタンス化されるであろう。

extension LevelImplementationType { 
    func navigate() { 

    } 
    func update(timeInterval: TimeInterval) { 

    } 
} 

LevelImpelmenationはLevelImplementationTypeに準拠する必要がありますが、それ以上の制約がありません。すなわちそれらは非常に異なる初期化剤を有することができる。

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 
    } 

} 

レベルインスタンスの杖はあなたが方法が拡張でデフォルトの実装を与えられているプロトコルに共通の機能を引き出すことができ

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

また、この愚かな質問を申し訳ありませんが、実装が構造体の場合は、なぜレベルベースがクラスですか? – MysteryPancake

+0

また、拡張機能を使ってプロトコルのデフォルトを定義しようとしているときに、filterBlockをどのように定義する必要がありますか?ブロックテーブルは、ベースレベルのファイルで、拡張子に存在しないので、私はそれにアクセスすることはできません: '拡張LevelImplementation { FUNCのfilterBlock(_ブロック:SKSpriteNode){ 不良ブロック= badBlocks.filter(){$ 0 !==ブロック} selectedBlocks = selectedBlocks.filter(){$ 0!==ブロック} } } '動作しません – MysteryPancake

+0

私は新しいスレッドを開始します – MysteryPancake

関連する問題