Reputation: 87
I am new to swift. In a group of classes / subclasses, I would like a variable in the super class to be within a required range. For example, in the following code.
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
}
}
}
What I don't like about the above, is that if I'm creating more subclasses for car, I'll always be forced to check that heading is within 0 and 360. I know about getters and setters, but is there a way to use a setter and still support incrementing the variable?
Ideally, I want my turnRight functions to look like:
func turnRight() {
heading = heading + 90
}
override func turnRight() {
speed = speed / 2
heading = heading + 90
}
...and for my variable set in the superclass to ensure that the heading is within 0 and 360.
Upvotes: 2
Views: 459
Reputation: 2405
what about move heading logic into separate structure?
Demo code is shown above.
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: Update new solution with typealias and generic function turn by angle and enum values
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
}
}
Upvotes: 1
Reputation: 53161
Consider using didSet
on 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()
}
}
Upvotes: 1
Reputation: 130122
While the implementation in Vehicle
could be simpler, instead of repeating the implementation you can simply call the original implementation:
override func turnRight() {
speed = speed / 2
super.turnRight()
}
For a simpler implementation, we can, for example:
var heading: Int {
didSet {
if heading < 0 {
heading = heading % 360 + 360
} else {
heading = heading % 360
}
}
}
Then turning can be done just using self.heading += 90
.
Upvotes: 1