Introduction to Object Oriented Programming & Design
Slides version: lecture7_slides.html Website version: lecture7.html
- What is Object Oriented Programming?
- What is Object Oriented Analysis and Design?
- Object Oriented Analysis
- Example: Calculator
- Use cases
- Object models
- Example: Calculator
- Object Oriented Design
- Example: Calculator
- System Design
- Object Design
- Example: Calculator
- Object Oriented Implementation
- Example: Calculator
- Summary
- Pratices
What is Object Oriented Programming?
Example: Calculator
C | ± | % | / |
7 | 8 | 9 | * |
4 | 5 | 6 | - |
1 | 2 | 3 | + |
0 | . | = |
A calculator consists of a set of buttons, each of which has following functions:
- Numbers:
1
,2
,3
,4
,5
,6
,7
,8
,9
,0
- Operations:
+
,-
,*
,/
- Symbols: ±(
p
lusminus),%
,.
- Function:
=
,C
(lear)
So, we can model the calculator as a class. For example:
class Button
{
// ...
};
class Calc_Controller
{
// ...
};
class Calculator
{
// ...
};
But, how?
What is Object Oriented Analysis and Design?
Object-oriented analysis and design - Wikipedia
Object-oriented analysis and design (OOAD) is a technical approach for analyzing and designing an application, system, or business by applying object-oriented programming, as well as using visual modeling throughout the software development process to guide stakeholder communication and product quality.
Object Oriented Analysis
First, we need to review the use cases and list the object models.
Use case: Calculator
- A calculator consists of a set of buttons, each of which has following functions:
- Numbers:
1
,2
,3
,4
,5
,6
,7
,8
,9
,0
- Operations:
+
,-
,*
,/
- Symbols: ±(
p
lusminus),%
,.
- Function:
=
,C
(lear)
- Numbers:
- User want to type in a number, user need to press number buttons or
.
, from left to right- If the number is a percentage, press
%
after finish typing a number - If the number is a negative number, press
±
after finish typing a number - If the typed number is wrong, press
C
to clear the number
- If the number is a percentage, press
- After finish typing a number, user need to press an operation button
- perform the previous operation with the current result and the typed number
- If the typed number is the first number, set the result with the typed number, as the same as the user press
=
in 2.
- If the typed number is the first number, set the result with the typed number, as the same as the user press
- Do 1. to 3. until user press
=
Object models: Calculator
Next, we need to list the objects and their attributes.
Calculator:
- result: number
- buttons:
- Numbers:
1
,2
,3
,4
,5
,6
,7
,8
,9
,0
- Operations:
+
,-
,*
,/
- Symbols: ±(
p
lusminus),%
,.
- Function:
=
,C
(lear)
- Numbers:
- controller
- a button is pressed
- a number is typed
C
lear is pressed±
is pressed%
is pressed.
is pressed
- an operation is pressed
=
is pressed
Object Oriented Design
After we have the object models, we can design the system and the objects.
System Design
Calculator:
- input: buttons
- output: result
- status: result, controller, buttons
Use cases:
- send which button is pressed to controller
- send result to controller as the input of previous operation
- contoller will update the result of the calculator with the input number, operation, and the previous result
Object Design
Botton:
- identify which button is pressed
- send which button is pressed
Controller
- translate the pressed buttons to the corresponding actions:
- a number is typed
C
lear is pressed±
is pressed%
is pressed
- an operation is pressed
=
is pressed
- a number is typed
- get the previous result
- send the result to the calculator
Object Oriented Implementation
Finally, we can implement the system and the objects.
Botton
class Button
{
protected:
char symbol;
public:
Button(char arg_btn_char)
: symbol(arg_btn_char)
{
}
virtual char press() const // polymorphism, will discuss in lecture 11
{
return '\0';
}
};
class Num_Button : public Button // inherits from Button, will discuss in next lecture
{
public:
Num_Button(char arg_btn_char = '\0') : Button(arg_btn_char)
{
// ...
}
char press() const
{
return symbol;
}
};
class Op_Button : public Button
{
public:
Op_Button(char arg_btn_char = '\0') : Button(arg_btn_char)
{
// ...
}
char press() const
{
return symbol;
}
};
class Sym_Button : public Button
{
public:
Sym_Button(char arg_btn_char = '\0') : Button(arg_btn_char)
{
// ...
}
char press() const
{
return symbol;
}
};
class Func_button : public Button
{
public:
Func_button(char arg_btn_char = '\0') : Button(arg_btn_char)
{
// ...
}
char press() const
{
return symbol;
}
};
Controller
class Calc_Controller
{
private:
int status; // 0 = init, 1 = type num, 2 = press op or assign
char next_op;
char curr_op;
bool decimal_pressed;
double type_num;
bool minus_pressed;
int decimal_offset;
public:
Calc_Controller()
: status(0), next_op('='), curr_op('='), decimal_pressed(false),
type_num(0), minus_pressed(false), decimal_offset(1)
{
}
void button_pressed(Button &arg_btn)
{
switch (status)
{
case 0:
if (typeid(arg_btn) == typeid(Num_Button))
{
status = 1;
type_num = arg_btn.press() - '0';
}
else if (typeid(arg_btn) == typeid(Op_Button))
{
status = 2;
next_op = arg_btn.press();
}
else if (typeid(arg_btn) == typeid(Sym_Button))
{
status = 1;
switch (arg_btn.press())
{
case '.':
decimal_pressed = true;
break;
case 'p':
minus_pressed = true;
break;
default:
break;
}
}
else if (typeid(arg_btn) == typeid(Func_button))
{
status = 0;
next_op = '=';
arg_btn.press();
}
break;
case 1:
if (typeid(arg_btn) == typeid(Num_Button))
{
if (decimal_pressed)
{
decimal_offset *= 10;
}
type_num *= 10;
type_num += arg_btn.press() - '0';
}
else if (typeid(arg_btn) == typeid(Op_Button))
{
status = 2;
curr_op = next_op;
next_op = arg_btn.press();
type_num = type_num * (minus_pressed ? -1 : 1) / decimal_offset;
}
else if (typeid(arg_btn) == typeid(Sym_Button))
{
switch (arg_btn.press())
{
case '.':
decimal_pressed = true;
break;
case 'p':
minus_pressed = !minus_pressed;
break;
case '%':
type_num = type_num * 0.01;
break;
default:
break;
}
}
else if (typeid(arg_btn) == typeid(Func_button))
{
switch (arg_btn.press())
{
case 'c':
type_num = 0;
break;
case '=':
curr_op = next_op;
next_op = arg_btn.press();
status = 2;
type_num = type_num * (minus_pressed ? -1 : 1) / decimal_offset;
}
}
break;
case 2:
if (typeid(arg_btn) == typeid(Num_Button))
{
status = 1;
type_num = arg_btn.press() - '0';
}
else if (typeid(arg_btn) == typeid(Op_Button))
{
next_op = arg_btn.press();
}
else if (typeid(arg_btn) == typeid(Sym_Button))
{
status = 1;
switch (arg_btn.press())
{
case '.':
decimal_pressed = true;
break;
case 'p':
minus_pressed = !minus_pressed;
break;
case '%':
type_num = type_num * 0.01;
break;
default:
break;
}
}
else if (typeid(arg_btn) == typeid(Func_button))
{
switch (arg_btn.press())
{
case 'c':
type_num = 0;
status = 0;
curr_op = '=';
next_op = '=';
break;
case '=':
curr_op = '=';
next_op = '=';
break;
}
}
break;
}
}
double update_result(const double &arg_result)
{
switch (status)
{
case 0:
return arg_result;
case 1:
return arg_result;
case 2:
switch (curr_op)
{
case '+':
return arg_result + type_num;
case '-':
return arg_result - type_num;
case '*':
return arg_result * type_num;
case '/':
return arg_result / type_num;
case '=':
return type_num;
default:
return arg_result;
}
}
return arg_result;
}
};
Calculator
class Calculator
{
private:
double result;
Calc_Controller controller;
Num_Button num_buttons[10];
Op_Button op_buttons[4];
Sym_Button sym_buttons[3];
Func_button func_buttons[2];
void _run()
{
controller.button_pressed(num_buttons[1]); // 1
result = controller.update_result(result);
controller.button_pressed(op_buttons[0]); // +
result = controller.update_result(result);
controller.button_pressed(num_buttons[2]); // 2
result = controller.update_result(result);
controller.button_pressed(func_buttons[1]); // =
result = controller.update_result(result);
}
public:
Calculator() // like we turn on a calculator
: result(0.0), controller()
{
// init num_buttons
for (int i = 0; i < 10; i++)
{
num_buttons[i] = Num_Button(i + '0');
}
// init op_buttons
op_buttons[0] = Op_Button('+');
op_buttons[1] = Op_Button('-');
op_buttons[2] = Op_Button('*');
op_buttons[3] = Op_Button('/');
// init sym_buttons
sym_buttons[0] = Sym_Button('.');
sym_buttons[1] = Sym_Button('p');
sym_buttons[2] = Sym_Button('%');
// init func_buttons
func_buttons[0] = Func_button('C');
func_buttons[1] = Func_button('=');
_run();
}
~Calculator() // like we turn off a calculator
{
}
};
int main()
{
Calculator calc;
return 0;
}
Summary
4 steps to perform object-oriented programming:
- Define use cases
- Define objects by use cases
- Define whole system by objects
- Detail define objects and their properties
- Implement objects and system
Pratices
Use the workflow above to implement the following problems:
- Elevator system
- Basketball game
- Closet