2017-04-22 1 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) 
    } 

} 

수준

는 객체 인스턴스화 될 또는 확장을 통해 수행 할 수 있습니다 LevelImplementationType

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

기본 구현에 부합하는 구조체.

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 = badBlocks.filter() {$ 0 ! == block} selectedBlocks = selectedBlocks.filter() {$ 0! == block} } }'작동하지 않습니다. – MysteryPancake

+0

새 스레드를 시작하겠습니다. – MysteryPancake