import types class RangeError(Exception): """ raised when a value is out of legal range """ pass class Angle: """ Encapsulates an Integer 0 <= angle < 360 """ def __init__(self, value=0): """ Angle([0 <= value:Integer = 0 < 360]) constructor. """ self.setValue(value) def __str__(self): """ __str__() -> String representation of an Angle. Example: str(Angle(20)) returns "<Angle:20>" """ return "<Angle:%d>" % (self.getValue()) def getValue(self): """ getValue() -> Integer in [0,360[ Get the Angle value. """ return self.__data def setValue(self, value=0): """ setValue([0 <= value:Integer = 0 < 360]) -> Set the Angle value. The value is kept in a private variable __data Raises: TypeError if value is not an Integer RangeError if value not in [0, 360[ range """ if type(value) != types.IntType: raise TypeError, "Angle value must be an Integer" if not (0 <= value < 360): raise RangeError, "Angle value must be in [0, 360[ range" self.__data = value def __add__(self, angle): """ __add__(angle:Angle or Integer) --> Angle object, sum of self and angle Raises: TypeError if angle argument is not an Integer nor an Angle RangeError if an Integer angle argument is not in [0, 360[ range """ if type(angle) == types.IntType: if (0 <= angle < 360): return Angle(self.getValue()+angle) else: raise RangeError, "angle value must be in [0, 360[ range" elif type(angle) == type(Angle()): return Angle(self.getValue()+angle.getValue()) else: raise TypeError, "angle argument must be either Integer or Angle" class Aircraft: """ Encapsulates Aircraft properties. """ # Class variable keeping track of total number of aircraft # Access by means of Aircraft.NumAircraft NumAircraft = 0 def __init__(self, heading=None): """ __init__([heading:Angle|[0,360[ = Angle(0)]) Aircraft constructor. """ if heading is None: self.__heading = Angle(0) # default heading (mutable) elif type(heading) == type(Angle()): self.__heading = heading else: raise TypeError, "heading must be of Angle type" Aircraft.NumAircraft += 1 # class attribute self.__UID = Aircraft.NumAircraft # Unique aircraft ID def __str__(self): """ __str__() -> String representation of an Aircraft instance. Example: str(Aircraft(Angle(20))) returns "<Aircraft:3:<Angle:20>>" """ return "<Aircraft:%d:%s>" % (self.getUID(),str(self.getHeading())) def getUID(self): """ getUID() -> Unique aircraft ID (Integer) """ return self.__UID def getHeading(self): """ getHeading() -> Angle """ return self.__heading def turn(self, angle=None): """ turn([angle:Angle|[0,360[ = Angle(0)]) adds angle to heading. """ if angle is None: self.__heading = self.getHeading() + Angle(0) else: # type/range checking of angle is done in the Angle class self.__heading = self.getHeading() + angle class Glider(Aircraft): """ Encapsulates Glider (a special kind of Aircraft) properties. """ def __init__(self, heading=None): """ __init__([heading:Angle|[0,360[ = Angle(0)]) Glider constructor. """ Aircraft.__init__(self, heading) # superclass' constructor self.__towlineAttached = 0 # no towline attached def __str__(self): """ __str__() -> String representation of a Glider instance. Example: str(Glider(Angle(20))) returns "<Glider:<Aircraft:3:<Angle:20>>:Not Attached>" """ if self.towlineAttached(): self.__attachedString = "Attached" else: self.__attachedString = "Not Attached" return "<Glider:%s:%s>" % (Aircraft.__str__(self),self.__attachedString) def towlineAttached(self): """ towlineAttached() -> 0|1 (whether towline is attached). """ return self.__towlineAttached def attachTowline(self): """ attachTowline() attaches towline. """ if self.towlineAttached(): print "Warning: towline is already attached" else: self.__towlineAttached = 1 def detachTowline(self): """ detachTowline() detaches towline. """ if not self.towlineAttached(): print "Warning: no towline to detache" else: self.__towlineAttached = 0 class PassengerVehicle: """ Encapsulates an infinite capacity Passenger Vehicle's properties (number of passengers). """ def __init__(self, passengers=0): """ __init__([passengers:PosInteger = 0]) PassengerVehicle constructor. """ self.__checkPassengerType(passengers) self.__passengers = passengers def __checkPassengerType(self, passengers): """ __checkPassengerType(passengers) Raises TypeError if non-Integer or negative argument """ if type(passengers) != types.IntType: raise TypeError, "only Integer number of passengers allowed" elif passengers < 0: raise TypeError, "only non-negative number of passengers allowed" def __str__(self): """ __str__() -> String representation of a PassengerVehicle instance. Example: str(PassengerVehicle(10)) returns "<PassengerVehicle:10>" """ return "<PassengerVehicle:%d>" % (self.numPassengers()) def numPassengers(self): """ numPassengers() -> number of passengers (Integer) """ return self.__passengers def board(self, passengers=0): """ board([passengers:PosInteger = 0]) board passengers """ self.__checkPassengerType(passengers) self.__passengers += passengers def unload(self, passengers=0): """ board([passengers:PosInteger = 0]) unload passengers """ self.__checkPassengerType(passengers) if passengers > self.numPassengers(): print "Cannot unload more passengers than present on vehicle" else: self.__passengers -= passengers def isEmpty(self): """ isEmpty() -> 1|0 empty status of the vehicle """ return self.numPassengers() == 0 class PassengerAircraft(Aircraft, PassengerVehicle): """ Encapsulates properties of both Aircraft and PassengerVehicle. (multiple inheritance) """ def __init__(self): """ __init__() PassengerAircraft constructor. """ Aircraft.__init__(self) # Aircraft baseclass constructor PassengerVehicle.__init__(self) # PassengerVehicle baseclass constructor def __str__(self): """ __str__() -> String representation of a PassengerAircraft instance. Example: str(PassengerAircraft()) for the third instantiated Aircraft returns "<PassengerAircraft:<Aircraft:3:<Angle:20>>:<PassengerVehicle:0>>" """ return "<PassengerAircraft:%s:%s>" % (Aircraft.__str__(self), PassengerVehicle.__str__(self))