Title: Inheritance
1??? 8?????? ?????? ???????? 7-9
2 1. Initializer
3Inheritance
- Make the PressureSensor and TemperatureSensor
inherit from the base class Sensor. - Add directed associations from the Motor to
the PressureSensor and to the TemperatureSensor. - Set the multiplicity to 1.
4Base Class Sensor
- Add attribute name of type OMString
- Add a constructor that receives an argument aName
of type OMString - Initialize the attribute in the initializer
name(aName) - Create an operation print with implementation
stdcout ltlt name ltlt
5Base Class Sensor-Sensor.cpp
- //file Sensor.cpp
- include Sensor.h
- SensorSensor(OMString aName) name(aName)
- void Sensorprint() stdcout ltlt name ltlt
-
6Motor Class
- Create a constructor that creates instances of
both types of Sensor - setItsTemperatureSensor(new TemperatureSensor(T1
)) - setItsPressureSensor(new PressureSensor(P1))
7Class Motor- Motor.cpp
- //file Motor.cpp
- include Motor.cpp
- include Sensor.h
- MotorMotor()
-
- setItsTemperatureSensor(new TemperatureSensor(
T1)) - setItsPressureSensor(new PressureSensor(P1))
-
-
8Derived Sensor Classes
- For both derived Sensor classes
- Create a constructor that has an argument aName
of type OMString - Set the Initializer to Sensor(aName)
Sensor(aName)
invokes the Sensor constructor so as to
initialize the name field of the base class.
9Derived Classes TemperatureSensor.cpp
- //file TemperatureSensor.cpp
- include TemperatureSensor.h
- TemperatureSensorTemperatureSensor(OMString
aName) Sensor(aName) -
10Animating
- Create a Test component and a Debug configuration
that creates an initial instance of the Motor
class - Save / Generate / Make / Run
- With the browser, note that there are two
instances of Sensor. Each Sensor has a name that
has been initialized.
11User Types
- Using the browser, right-click on the Default
package and select Add New Type - add a type tTempUnits declared as
- enum tTempUnits CELSIUS, FAHRENHEIT
An alternative declaration is enum s
CELSIUS, FAHRENHEIT .
12Attribute Unit
- Add an attribute unit of type tTempUnits for the
TemperatureSensor. - Add an argument to the TemperatureSensor
constructor called aUnit of the same type - In the initializer add ,unit(aUnit)
13TemperatureSensor
- Change the read operation to
- stdcout ltlt Temperature ltlt rand() 100 ltlt
deg - if ( unit CELSIUS )
- stdcout ltlt C ltlt stdendl
- else
- stdcout ltlt F ltlt stdendl
- In the Motor constructor, add the argument
CELSIUS as follows - setItsTemperatureSensor (new
TemperatureSensor( T1, CELSIUS))
142. Container Classes (OMCollection)andIterators
(OMIterator)
15Using OMIterator
- Rhapsody provides an OMIterator class that can be
used as follows to iterate through a container
OMCollectionltSensorgt itsSensor // a
container OMIteratorltSensorgt iSensor(itsSensor)
iSensor.reset() // point to first while (
iSensor ! NULL ) (iSensor)-gtprint() //
print iSensor // point to next
16Collection of Sensors
- Load the Virtual project and save as
Collection - Delete from Model the relations between the Motor
and the Sensors. Check in the Browser that these
relations have been deleted from the model not
just the view. - Add a directed aggregation itsSensor from
the Motor to the Sensor. Set Multiplicity to
(many).
17OMCollection
- Delete implementation of Motor constructor
- Save / Generate / Examine code for Motor
- Note that the relation has been implemented as a
collection of Sensors - OMCollectionltSensorgt
itsSensor - Note also that there is an operation
- addItsSensor(Sensor
p_Sensor)
18OMCollection Motor.h
- ifndef Motor_H
- define Motor_H
- include "PressureSensor.h"
- include "TemperatureSensor.h"
- class Sensor
- public //defined by user
- void addSensor()
- void deleteSensor()
- void pollSensors()
- public //defined by Rhapsody
- OMIteratorltSensorgt getItsSensor() const
-
- void addItsSensor(Sensor p_Sensor)
- void removeItsSensor(Sensor p_Sensor)
- void clearItsSensor()
- protected
- OMCollectionltSensorgt itsSensor
19Adding to OMCollection
- In the motor constructor add Sensors
- addItsSensor(new TemperatureSensor(Sensor1,CELSI
US)) - addItsSensor(new TemperatureSensor(Sensor2,FAHRE
NHEIT)) - addItsSensor(new PressureSensor(Sensor3) )
202.a Dependencies
21Dependencies
- In order to compile, the Motor needs to include
the Pressure and Temperature Sensors header
files. To do this we will add dependencies
from the Motor to those classes - Double-click on each dependency and select
the stereotype Usage.
22Implementation Includes
- Alternatively instead of drawing dependencies, we
can just modify the properties for the Motor
class and for CPP_CG-gtClass-gtImpIncludes add
TemperatureSensor.h,PressureSensor.h
CPP_CG means C Code Generation.
23Multiple Relation
- Save / Generate / Make / Run
- Show that the Motor has a collection of three
Sensors.
24Statechart
- Create a simple Statechart for the Motor class
that calls a pollSensors() routine every two
seconds.
25pollSensors()
- Create the pollSensors() operation that will poll
all the Sensors in the collection
OMIteratorltSensorgt iSensor(itsSensor) for (
iSensor.reset() iSensor iSensor )
(iSensor)-gtprint() (iSensor)-gtread()
cout ltlt "---------------------" ltlt endl
Note that if any more Sensors of any other type
are added, the operation still functions!
26Extended Exercise
- For the Sensor class, add a static attribute
numberOfSensors of type int with initial value 0. - In the Sensor Constructor add numberOfSensors
- For the Sensor class, add a virtual Destructor
with implementation numberOfSensors-- - Add the following to pollSensors()
- cout ltlt Number of sensors ltlt
SensorgetNumberOfSensors() ltlt endl - Generate code and execute to check that
numberOfSensors 3.
273. Threads, Active Classes, Statechart Inheritance
28Concurrency
- We want each Sensor to run on its own thread
(active class). - To do so, we need each Sensor to be Reactive
(class that waits for events). - So we will create a Statechart for the base
Sensor class as follows
29Active Classes
- With the browser, change the concurrency of the
Sensor class from sequential to active.
30Inheriting Behavior
- Open the Statecharts for the PressureSensor and
TemperatureSensor. Note that they have inherited
the base class Statechart. - Specialize the behavior of the TemperatureSensor
as below
Grayed out indicating inherited behavior
31Starting the Behavior
- Add a call to startBehavior() from the
TemperatureSensor and PressureSensor constructors
to initialize the statecharts.
If we had used a composite class, Rhapsody would
have done this for us, but that would have been
too easy !
32Multi-threads
- Save / Generate / Make / Run
- Check that there are four active threads.
- Setting the focus to a particular thread displays
the call stack and event queue for that thread.
There will always be one thread called mainThread.
33Suspending Threads
- Note that a thread can be suspended.
34Problems with the Design
- With the current design there are a few potential
problems - The Motor class needs to know about all the
different types of Sensor. - If another class wants access to the Sensors, it
too will need to depend upon all the different
types of Sensor. - Starting the behavior of a Sensor, in the
constructor is not very elegant. - Adding a new type of Sensor means finding and
modifying all classes that use Sensor.
354. Singleton, Abstract Factory
36Improving the Design
- Using the factory method design pattern will
solve all these concerns. - A SensorFactory class can be introduced that is
used by all classes ( ex Motor ) that need to
get a Sensor. This decouples the Motor class from
the actual Sensors and can also start the
behavior of the Sensors. - The SensorFactory will be implemented using the
Singleton design pattern (to ensure that there
is only one instance of SensorFactory).
See the SensorFactory example.
37The Improved Design
38The Singleton Design Pattern I
Static attribute
Protected constructor
39The Singleton Design Pattern II
Static factory operation
Calling the createRandomSensor operation
40SensorFactorycreateRandomSensor()
- Sensor SensorFactorycreateRandomSensor()
- Sensor aSensor
- OMString aName
- char index10
- //itoa(SensorgetCount(), index, 10)
- strcpy ( index, "1" )
- aName "Sensor" OMString(index)
- switch ( rand() 4 )
- default
- case 0 aSensor new TemperatureSensor(
aName, CELSIUS ) - break
- case 1 aSensor new TemperatureSensor(
aName, FAHRENHEIT ) - break
- case 2 aSensor new PressureSensor( aName
) - break
- case 3 aSensor new SpeedSensor( aName )
- break