2017-01-24 14 views
1

Я новичок в быстром. В группе классов/подклассов я хотел бы, чтобы переменная в суперклассе находилась в пределах требуемого диапазона. Например, в следующем коде.Настройка требований для переменных класса в Swift

class Vehicle { 
    var speed: Int 
    var heading: Int 

    init(speed: Int, heading: Int) { 
     self.speed = speed 
     self.heading = heading 
    } 

    func turnRight() { 
     if 360 - heading < 90 { 
      heading = heading - 270 
     } else { 
      heading = heading + 90 
     } 
    } 
} 

class Car : Vehicle { 
    init(speed: Int, heading: Int) { 
     super.init(speed: speed, heading: heading) 
    } 

    override func turnRight() { 
     speed = speed/2 
     if 360 - heading < 90 { 
      heading = heading - 270 
     } else { 
      heading = heading + 90 
     } 
    } 
} 

Что мне не нравится выше, является то, что если я создаю более подклассы для автомобиля, я всегда буду вынужден проверить, что заголовок находится в пределах 0 и 360. Я знаю о добытчиках и сеттеров, но есть ли способ использовать сеттер и по-прежнему поддерживать приращение переменной?

В идеале, я хочу, чтобы мои функции TurnRight выглядеть следующим образом:

func turnRight() { 
    heading = heading + 90 
} 

override func turnRight() { 
    speed = speed/2 
    heading = heading + 90 
} 

... и для моей переменной набор в суперкласс, чтобы обеспечить, что заголовок находится в пределах 0 и 360.

+0

Ну, вы могли бы создать функцию, называемую changeHeadingBy с поплавком в качестве параметра, то просто вызвать эту функцию вместо того, чтобы проверить осанку каждый раз. Затем используйте это вместо вашего «добавления» во втором примере. – SaylorTwift2

+0

Почему бы вам просто не называть 'super.turnRight()'? – Sulthan

ответ

1

насчет переместить логику заголовка в отдельную структуру?

Демонстрационный код показан выше.

struct Heading { 

    private var heading = 0 
    init(initialHeading: Int) { 
     heading = initialHeading 
    } 
    mutating func turnRight(){ 
     if 360 - heading < 90 { 
      heading = heading - 270 
     } else { 
      heading = heading + 90 
     } 
    } 
} 

class Vehicle { 
    var speed: Int 
    var heading: Heading 

    init(speed: Int, heading: Int) { 
     self.speed = speed 
     self.heading = Heading(initialHeading: heading) 
    } 

    func turnRight() { 
     heading.turnRight() 
    } 
} 

class Car : Vehicle { 
    override init(speed: Int, heading: Int) { 
     super.init(speed: speed, heading: heading) 
    } 

    override func turnRight() { 
     speed = speed/2 
     super.turnRight() 
    } 
} 

EDIT: Обновление новое решение с typealias и общей функцией поворота на угол и перечисления значений

typealias Angle = Int 

enum Direction: Angle { 
    case left = -90 
    case right = 90 } 

struct Heading { 

    private var heading : Angle 
    init(initialHeading: Angle) { 
     heading = initialHeading 
    } 

    mutating func turnBy(angle: Angle){ 
     if 360 - heading < angle { 
      heading = heading - (360 - angle) 
     } else { 
      heading = heading + angle 
     } 
    } 
} 

class Vehicle { 
    var speed: Int 
    var heading: Heading 

    init(speed: Int, heading: Int) { 
     self.speed = speed 
     self.heading = Heading(initialHeading: heading) 
    } 

    func turnRight() { 
     heading.turnBy(angle: Direction.right.rawValue) 
    } 
} 

class Car : Vehicle { 
    override init(speed: Int, heading: Int) { 
     super.init(speed: speed, heading: heading) 
    } 

    override func turnRight() { 
     super.turnRight() 
     speed = speed/2 
    } 
} 
+1

Я бы также изменил 'turnRight' на' turn (angle:) ', но использование структуры - очень хорошая идея. – Sulthan

+0

@Sulthan Спасибо за идею. Я только что обновил оригинальный ответ с новым кодом с этой функцией, а enup и typealias –

+0

очень красиво - я еще не начал использовать структуры (я знаю, что они большая часть Swift, и я знаю немного C++, поэтому у меня есть некоторые знакомые). Но, похоже, это довольно понятная структура данных и отлично подходит для моего использования. Благодаря! –

1

Хотя реализация в Vehicle может быть проще, вместо того чтобы повторять реализации вы можете просто позвонить первоначальная реализация:

override func turnRight() { 
    speed = speed/2 
    super.turnRight() 
} 

Для более простой реализации мы п, к примеру:

var heading: Int { 
    didSet { 
     if heading < 0 { 
      heading = heading % 360 + 360 
     } else { 
      heading = heading % 360 
     } 
    } 
} 

Повернувшись может быть сделано только с помощью self.heading += 90.

+0

спасибо @Sulthan! –

1

Рассмотрите возможность использования didSet на heading

class Vehicle { 
    var speed: Int 
    var heading: Int { 
     didSet { 
      if heading > 360 { 
       heading -= 360 
      } else if heading < 0{ 
       heading += 360 
      } 
     } 
    } 

    init(speed: Int, heading: Int) { 
     self.speed = speed 
     self.heading = heading 
    } 

    func turnRight() { 
     heading += 90 
    } 
} 

class Car : Vehicle { 
    init(speed: Int, heading: Int) { 
     super.init(speed: speed, heading: heading) 
    } 

    override func turnRight() { 
     speed = speed/2 
     super.turnRight() 
    } 
} 
+0

Только незначительная точка, задающая 'заголовок'' '720', не будет держать ее в интервале' 0..360' :) – Sulthan

+0

_ «Ответ в спешке, покайтесь на досуге!» _ –

+0

Спасибо! Я наткнулся на didSet, но почему-то не думал, что это сработает в этом случае. Рад это видеть :) –