Can describe OOP at a higher level
Object-Oriented Programming (OOP) is a programming paradigm. A programming paradigm guides programmers to analyze programming problems, and structure programming solutions, in a specific way.
Programming languages have traditionally divided the world into two parts—data and operations on data. Data is static and immutable, except as the operations may change it. The procedures and functions that operate on data have no lasting state of their own; they’re useful only in their ability to affect data.
This division is, of course, grounded in the way computers work, so it’s not one that you can easily ignore or push aside. Like the equally pervasive distinctions between matter and energy and between nouns and verbs, it forms the background against which we work. At some point, all programmers—even object-oriented programmers—must lay out the data structures that their programs will use and define the functions that will act on the data.
With a procedural programming language like C, that’s about all there is to it. The language may offer various kinds of support for organizing data and functions, but it won’t divide the world any differently. Functions and data structures are the basic elements of design.
Object-oriented programming doesn’t so much dispute this view of the world as restructure it at a higher level. It groups operations and data into modular units called objects and lets you combine objects into structured networks to form a complete program. In an object-oriented programming language, objects and object interactions are the basic elements of design.
Some other examples of programming paradigms are:
| Paradigm | Programming Languages |
|---|---|
| Procedural Programming paradigm | C |
| Functional Programming paradigm | F#, Haskel, Scala |
| Logic Programming paradigm | Prolog |
Some programming languages support multiple paradigms.
Java is primarily an OOP language but it supports limited forms of functional programming and it can be used to (although not recommended) write procedural code. e.g. se-edu/addressbook-level1
JavaScript and Python support functional, procedural, and OOP programming.
Exercises
statements about OOP
A) Choose the correct statements
- a. OO is a programming paradigm
- b. OO guides us in how to structure the solution
- c. OO is mainly an abstraction mechanism
- d. OO is a programming language
- e. OO is modeled after how the objects in real world work
B) Choose the correct statements
- a. Java and C++ are OO languages
- b. C language follows the Functional Programming paradigm
- c. Java can be used to write procedural code
- d. Prolog follows the Logic Programming paradigm
A) (a)(b)(c)(e)
Explanation: While many languages support the OO paradigm, OO is not a language itself.
B) Choose the correct statement
(a)(b)(c)(d)
Explanation: C follows the procedural paradigm. Yes, we can write procedural code using OO languages e.g., AddressBook-level1.
procedural vs OOP
OO is a higher level mechanism than the procedural paradigm.
True.
Explanation: Procedural languages work at simple data structures (e.g., integers, arrays) and functions level. Because an object is an abstraction over data+related functions, OO works at a higher level.
Can describe how OOP relates to the real world
Every object has both state (data) and behavior (operations on data). In that, they’re not much different from ordinary physical objects. It’s easy to see how a mechanical device, such as a pocket watch or a piano, embodies both state and behavior. But almost anything that’s designed to do a job does, too. Even simple things with no moving parts such as an ordinary bottle combine state (how full the bottle is, whether or not it’s open, how warm its contents are) with behavior (the ability to dispense its contents at various flow rates, to be opened or closed, to withstand high or low temperatures).
It’s this resemblance to real things that gives objects much of their power and appeal. They can not only model components of real systems, but equally as well fulfill assigned roles as components in software systems.
Object Oriented Programming (OOP) views the world as a network of interacting objects.
A real world scenario viewed as a network of interacting objects:
You are asked to find out the average age of a group of people Adam, Beth, Charlie, and Daisy. You take a piece of paper and pen, go to each person, ask for their age, and note it down. After collecting the age of all four, you enter
it into a calculator to find the total. And then, use the same calculator to divide the total by four, to get the average age. This can be viewed as the objects You, Pen, Paper, Calculator,
Adam, Beth, Charlie, and Daisy interacting to accomplish the end result of calculating the average age of the four persons. These objects can be considered as connected in a certain
network of certain structure.
OOP solutions try to create a similar object network inside the computer’s memory – a sort of a virtual simulation of the corresponding real world scenario – so that a similar result can be achieved programmatically.
OOP does not demand that the virtual world object network follow the real world exactly.
Our previous example can be tweaked a bit as follows:
- Use an object called
Mainto represent your role in the scenario. - As there is no physical writing involved, we can replace the
PenandPaperwith an object calledAgeListthat is able to keep a list of ages.
Every object has both state (data) and behavior (operations on data).
| Object | Real World? | Virtual World? | Example of State (i.e. Data) | Examples of Behavior (i.e. Operations) |
|---|---|---|---|---|
| Adam | Name, Date of Birth | Calculate age based on birthday | ||
| Pen | - | Ink color, Amount of ink remaining | Write | |
| AgeList | - | Recorded ages | Give the number of entries, Accept an entry to record | |
| Calculator | Numbers already entered | Calculate the sum, divide | ||
| You/Main | Average age, Sum of ages | Use other objects to calculate |
Every object has an interface and an implementation.
Every real world object has:
- an interface through which other objects can interact with it
- an implementation that supports the interface but may not be accessible to the other object
The interface and implementation of some real-world objects in our example:
- Calculator: the buttons and the display are part of the interface; circuits are part of the implementation.
- Adam: In the context of our 'calculate average age' example, the interface of Adam consists of requests that adam will respond to, e.g. "Give age to the nearest year, as at Jan 1st of this year" "State your name"; the implementation includes the mental calculation Adam uses to calculate the age which is not visible to other objects.
Similarly, every object in the virtual world has an interface and an implementation.
The interface and implementation of some virtual-world objects in our example:
Adam: the interface might have a methodgetAge(Date asAt); the implementation of that method is not visible to other objects.
Objects interact by sending messages. Both real world and virtual world object interactions can be viewed as objects sending message to each other. The message can result in the sender object receiving a response and/or the receiver object’s state being changed. Furthermore, the result can vary based on which object received the message, even if the message is identical (see rows 1 and 2 in the example below).
Examples:
| World | Sender | Receiver | Message | Response | State Change |
|---|---|---|---|---|---|
| Real | You | Adam | "What is your name?" | "Adam" | - |
| Real | as above | Beth | as above | "Beth" | - |
| Real | You | Pen | Put nib on paper and apply pressure | Makes a mark on your paper | Ink level goes down |
| Virtual | Main | Calculator (current total is 50) | add(int i): int i = 23 | 73 | total = total + 23 |
Exercises
Describe objects in the given scenario
Consider the following real-world scenario.
Tom read a Software Engineering textbook (he has been assigned to read the book) and highlighted some of the text in it.
Explain the following statements about OOP using the above scenario as an example.
- Object Oriented Programming (OOP) views the world as a network of interacting objects.
- Every object has both state (data) and behavior (operations on data).
- Every object has an interface and an implementation.
- Objects interact by sending messages.
- OOP does not demand that the virtual world object network follow the real world exactly.
[1] Object Oriented Programming (OOP) views the world as a network of interacting objects.
Interacting objects in the scenario: Tom, SE Textbook (Book for short), Text, (possibly) Highlighter
objects usually match nouns in the description
[2]Every object has both state (data) and behavior (operations on data).
| Object | Examples of state | Examples of behavior |
|---|---|---|
Tom |
memory of the text read | read |
Book |
title | show text |
Text |
font size | get highlighted |
[3] Every object has an interface and an implementation.
- Interface of an object consists of how other objects interact with it i.e., what other objects can do to that object
- Implementation consist of internals of the object that facilitate the interactions but not visible to other objects.
| Object | Examples of interface | Examples of implementation |
|---|---|---|
Tom |
receive reading assignment | understand/memorize the text read, remember the reading assignment |
Book |
show text, turn page | how pages are bound to the spine |
Text |
read | how characters/words are connected together or fixed to the book |
[4] Objects interact by sending messages.
Examples:
Tomsends messageturn pageto theBookTomsends messageshow textto theBook. When theBookshows theText,Tomsends the messagereadto theTextwhich returns the text content toTom.Tomsends messagehighlightto theHighlighterwhile specifying whichTextto highlight. Then theHighlightersends the messagehighlightto the specifiedText.
[5] OOP does not demand that the virtual world object network follow the real world exactly.
Examples:
- A virtual world simulation of the above scenario can omit the
Highlighterobject. Instead, we can teachTextto highlight themselves when requested.
Can explain the abstraction aspect of OOP
The concept of Objects in OOP is an
Abstraction is a technique for dealing with complexity. It works by establishing a level of complexity we are interested in, and suppressing the more complex details below that level.
We can deal with a Person object that represents the person Adam and query the object for Adam's age instead of dealing with details such as Adam’s date of
birth (DoB), in what format the DoB is stored, the algorithm used to calculate the age from the DoB, etc.
Can explain the encapsulation aspect of OOP
Encapsulation protects an implementation from unintended actions and from inadvertent access.
-- Object-Oriented Programming with Objective-C, Apple
An object is an encapsulation of some data and related behavior in terms of two aspects:
1. The packaging aspect: An object packages data and related behavior together into one self-contained unit.
2. The information hiding aspect: The data in an object is hidden from the outside world and are only accessible using the object's interface.
Exercises
Choose the correct statement.
Choose the correct statements
- a. An object is an encapsulation because it packages data and behavior into one bundle.
- b. An object is an encapsulation because it lets us think in terms of higher level concepts such as Students rather than student-related functions and data separately.
Don't confuse encapsulation with abstraction.
Choose the correct statement
(a)
Explanation: The second statement should be: An object is an abstraction encapsulation because it lets ...
Can explain the relationship between classes and objects
Writing an OOP program is essentially writing instructions that the computer will use to,
- create the virtual world of the object network, and
- provide it the inputs to produce the outcome we want.
A class contains instructions for creating a specific kind of objects. It turns out sometimes multiple objects keep the same type of data and have the same behavior because they are of the same kind.
Instructions for creating a 'kind' (or ‘class’) of objects can be done once and that same instructions can be used to
Classes and objects in an example scenario
Consider the example of writing an OOP program to calculate the average age of Adam, Beth, Charlie, and Daisy.
Instructions for creating objects Adam, Beth, Charlie, and Daisy will be very similar because they are all of the same kind: they all represent ‘persons’ with the same interface, the same
kind of data (i.e. name, dateOfBrith, etc.), and the same kind of behavior (i.e. getAge(Date), getName(), etc.). Therefore, we can have a class called Person containing instructions
on how to create Person objects and use that class to instantiate objects Adam, Beth, Charlie, and Daisy.
Similarly, we need classes AgeList, Calculator, and Main classes to instantiate one each of AgeList, Calculator, and Main objects.
| Class | Objects |
|---|---|
Person |
objects representing Adam, Beth, Charlie, Daisy |
AgeList |
an object to represent the age list |
Calculator |
an object to do the calculations |
Main |
an object to represent you (i.e., the one who manages the whole operation) |
Exercises
Identify Classes and Objects
Consider the following scenario. If you were to simulate this in an OOP program, what are the classes and the objects you would use?
A customer (name: John) gave a cheque to the Cashier (name: Peter) to pay for the LoTR and GoT books he bought.
| Class | Objects |
|---|---|
Customer |
john |
Book |
LoTR, GoT |
Cheque |
checqueJohnGave |
Cashier |
peter |
Classes for CityConnect app
Assume you are writing a CLI program called CityConnect for storing and querying distances between cities. The behavior is as follows:
Welcome to CityConnect!Enter command: addroute Clementi BuonaVista 12Route from Clementi to BuonaVista with distance 12km addedEnter command: getdistance Clementi BuonaVistaDistance from Clementi to BuonaVista is 12Enter command: getdistance Clementi JurongWestNo route exists from Clementi to JurongWest!Enter command: addroute Clementi JurongWest 24Route from Clementi to JurongWest with distance 24km addedEnter command: getdistance Clementi JurongWestDistance from Clementi to JurongWest is 24Enter command: exit
What classes would you have in your code if you write your program based on the OOP paradigm?
One class you can have is Route
Can explain class-level members
While all objects of a class has the same attributes, each object has its own copy of the attribute value.
All Person objects have the Name attribute but the value of that attribute varies between Person objects.
However, some attributes are not suitable to be maintained by individual objects. Instead, they should be maintained centrally, shared by all objects of the class. They are like ‘global variables’ but attached to a specific class. Such variables whose value is shared by all instances of a class are called class-level attributes.
The attribute totalPersons should be maintained centrally and shared by all Person objects rather than copied at each Person object.
Similarly, when a normal method is being called, a message is being sent to the receiving object and the result may depend on the receiving object.
Sending the getName() message to the Adam object results in the response "Adam" while sending the same message to the Beth object results in the response "Beth".
However, there can be methods related to a specific class but not suitable for sending message to a specific object of that class. Such methods that are called using the class instead of a specific instance are called class-level methods.
The method getTotalPersons() is not suitable to send to a specific Person object because a specific object of the Person class should not have to know about the total number of Person objects.
Class-level attributes and methods are collectively called class-level members (also called static members sometimes because some programming languages use the keyword static to identify
class-level members). They are to be accessed using the class name rather than an instance of the class.
Exercises
Suitable as a class-level variables
Which of these are suitable as class-level variables?
- a. system: multi-player Pac Man game, Class:
Player, variable:totalScore - b. system: eLearning system, class:
Course, variable:totalStudents - c. system: ToDo manager, class:
Task, variable:totalPendingTasks - d. system: any, class:
ArrayList, variable:total(i.e., total items in a givenArrayListobject)
(c)
Explanation: totalPendingTasks should not be managed by individual Task objects and therefore suitable to be maintained as a class-level variable. The other variables should be managed at instance level as
their value varies from instance to instance. e.g., totalStudents for one Course object will differ from totalStudents of another.
Can explain the meaning of enumerations
An Enumeration is a fixed set of values that can be considered as a data type. An enumeration is often useful when using a regular data type such as int or String would allow invalid values to
be assigned to a variable.
Suppose you want a variable called priority to store the priority of something. There are only three priority levels: high, medium, and low. You can declare the variable
priority as of type int and use only values 2, 1, and 0 to indicate the three priority levels. However, this opens the possibility of an invalid values such as 9 being
assigned to it. But if you define an enumeration type called Priority that has three values HIGH, MEDIUM, LOW only, a variable of type Priority will never be assigned an invalid
value because the compiler is able to catch such an error.
Priority: HIGH, MEDIUM, LOW
Can explain associations
Objects in an OO solution need to be connected to each other to form a network so that they can interact with each other. Such connections between objects are called associations.
Suppose an OOP program for managing a learning management system creates an object structure to represent the related objects. In that object structure we can expect to have associations
between aCourse object that represents a specific course and Student objects that represents students taking that course.
Associations in an object structure can change over time.
To continue the previous example, the associations between a Course object and Student objects can change as students enroll in the module or drop the
module over time.
Associations among objects can be generalized as associations between the corresponding classes too.
In our example, as some Course objects can have associations with some Student objects, we can view it as an association between the Course class and the Student class.
Implementing associations
We use instance level variables to implement associations.
Can explain the meaning of navigability
When two classes are linked by an association, it does not necessarily mean both classes know about each other. The concept of which class in the association knows about the other class is called navigability.
Can explain the meaning of multiplicity
Multiplicity is the aspect of an OOP solution that dictates how many objects take part in each association.
The multiplicity of the association between Course objects and Student objects tells you how many Course objects can be associated with one
Student object and vice versa.
Implementing multiplicity
A normal instance-level variable gives us a 0..1 multiplicity (also called optional associations) because a variable can hold a reference to a single object or null.
In the code below, the Logic class has a variable that can hold 0..1 i.e., zero or one Minefield objects.
class Logic{ Minefield minefield;}class Minefield{ ...}
class Logic: def __init__(self, minefield): self.minefield = minefield # ...class Minefield: # ...
A variable can be used to implement a 1 multiplicity too (also called compulsory associations).
In the code below, the Logic class will always have a ConfigGenerator object, provided the variable is not set to null at some point.
class Logic { ConfigGenerator cg = new ConfigGenerator(); ...}
class Logic: def __init__(self): self.config_gen = ConfigGenerator()
Bi-directional associations require matching variables in both classes.
In the code below, the Foo class has a variable to hold a Bar object and vice versa i.e., each object can have an association with an object of the other type.
class Foo { Bar bar; //...}class Bar { Foo foo; //...}
class Foo: def __init__(self, bar): self.bar = bar;class Bar: def __init__(self, foo): self.foo = foo;
To implement other multiplicities, choose a suitable data structure such as Arrays, ArrayLists, HashMaps, Sets, etc.
This code uses an two-dimensional array to implement a 1-to-many association from the Minefield to Cell.
class Minefield { Cell[][] cell; ...}
class Minefield: def __init__(self): self.cells = {1:[], 2:[], 3:[]}
Can explain dependencies among classes
In the context of OOP associations, a dependency is a need for one class to depend on another without having a direct association with it. One cause of dependencies is interactions between objects that do not have a long-term link between them.
A Course object can have a dependency on a Registrar object to obtain the maximum number of students it can support.
Implementing dependencies
In the code below, Foo has a dependency on Bar but it is not an association because it is only a
Foo object and a Bar object. i.e. the Foo object does not keep the Bar object it receives as a parameter.
class Foo{ int calculate(Bar bar){ return bar.getValue(); }}class Bar{ int value; int getValue(){ return value; }}
class Foo: def calculate(self, bar): return bar.value;class Bar: def __init__(self, value): self.value = value
Can explain the meaning of composition
A composition is an association that represents a strong whole-part relationship. When the whole is destroyed, parts are destroyed too.
A Board (used for playing board games) consists of Square objects.
Composition also implies that there cannot be cyclical links.
The ‘sub-folder’ association between Folder objects is a composition type association. That means if the Folder object foo is a sub folder
of
Folder object bar, bar cannot be a sub-folder of foo.
Implementing composition
Composition is implemented using a normal variable. If correctly implemented, the ‘part’ object will be deleted when the ‘whole’ object is deleted. Ideally, the ‘part’ object may not even be visible to clients of the ‘whole’ object.
class Email { private Subject subject; ...}
class Email: def __init__(self): self.__subject = Subject()
In this code, the Email has a composition type relationship with the Subject class, in the sense that the subject is part of the email.
Can explain the meaning of aggregations
Aggregation represents a container-contained relationship. It is a weaker relationship than composition.
SportsClub can act as a container for Person objects who are members of the club. Person objects can survive without a SportsClub object.
Implementing aggregation
Implementation is similar to that of composition except the containee object can exist even after the container object is deleted.
In the code below, there is an aggregation association between the Team class and the Person in that a Team contains Person a
object who is the leader of the team.
class Team { Person leader; ... void setLeader(Person p) { leader = p; }}
class Team: def __init__(self): self.__leader = None def set_leader(self, person): self.__leader = person
Can explain the meaning of association classes
An association class represents additional information about an association. It is a normal class but plays a special role from a design point of view.
A Man class and a Woman class is linked with a ‘married to’ association and there is a need to store the date of marriage. However, that data is related
to the association rather than specifically owned by either the Man object or the Woman object. In such situations, an additional association class can be introduced, e.g. a Marriage class, to store such
information.
UML Class Diagrams → Association Classes → What UML/AssociationClasses
Implementing association classes
There is no special way to implement an association class. It can be implemented as a normal class that has variables to represent the endpoint of the association it represents.
In the code below, the Transaction class is an association class that represent a transaction between a Person who is the seller and another Person who is the buyer.
class Transaction{ //all fields are compulsory Person seller; Person buyer; Date date; String receiptNumber; Transaction (Person seller, Person buyer, Date date, String receiptNumber){ //set fields }}
Exercises
Which are suitable as an Association Class?
Which one of these is the suitable as an Association Class?
- a
- b
- c
- d
(a)(b)(c)(d)
Explanation: Mileage is a property of the car, and not specifically about the association between the Driver and the Car. If Mileage was defined as the total number of miles that car was driven by that driver, then it would be suitable as an association class.
Can explain the meaning of inheritance
The OOP concept Inheritance allows you to define a new class based on an existing class.
For example, you can use inheritance to define an EvaluationReport class based on an existing Report class so that the EvaluationReport class does not have to duplicate data/behaviors that are already implemented in the Report class. The EvaluationReport can inherit the wordCount attribute and the print() method from the
base class Report.
- Other names for Base class: Parent class, Super class
- Other names for Derived class: Child class, Sub class, Extended class
A superclass is said to be more general than the subclass. Conversely, a subclass is said to be more specialized than the superclass.
Applying inheritance on a group of similar classes can result in the common parts among classes being extracted into more general classes.
Man and Woman behaves the same way for certain things. However, the two classes cannot be simply replaced with a more general class Person because of the need to distinguish between Man and Woman for certain other things. A solution is to add the Person class as a superclass (to contain the code common to men and women) and let Man and Woman inherit from Person class.
Inheritance implies the derived class can be considered as a sub-type of the base class (and the base class is a super-type of the derived class), resulting in an is a relationship.
Inheritance does not necessarily mean a sub-type relationship exists. However, the two often go hand-in-hand. For simplicity, at this point let us assume inheritance implies a sub-type relationship.
To continue the previous example,
Womanis aPersonManis aPerson
Inheritance relationships through a chain of classes can result in inheritance hierarchies (aka inheritance trees).
Two inheritance hierarchies/trees are given below. Note that the triangle points to the parent class. Observe how the Parrot is a Bird as well as it is an Animal.
Multiple Inheritance is when a class inherits directly from multiple classes. Multiple inheritance among classes is allowed in some languages (e.g., Python, C++) but not in other languages (e.g., Java, C#).
The Honey class inherits from the Food class and the Medicine class because honey can be consumed as a food as well as a medicine (in some oriental medicine practices).
Similarly, a Car is an Vehicle, an Asset and a Liability.

Exercises
Which statements are correct
Which of these are correct?
- a. Superclass is more general than the subclass.
- b. Child class is more specialized than the parent class.
- c. A class can inherit behavior from its ancestor classes (ancestor classes = classes above it in the inheritance hierarchy).
- d. Code reuse can be one benefit of inheritance.
- e. A change to the superclass will not affect its subclasses.
(a) (b) (c) (d)
Explanation: (e) is incorrect. Because subclasses inherit behavior from the superclass, any changes to the superclass could affect subclasses.
Can explain method overriding
Method overriding is when a sub-class changes the behavior inherited from the parent class by re-implementing the method. Overridden methods have the same name, same type signature, and same return type.
Consider the following case of EvaluationReport class inheriting the Report class:
Report methods |
EvaluationReport methods |
Overrides? |
|---|---|---|
print() |
print() |
Yes |
write(String) |
write(String) |
Yes |
read():String |
read(int):String |
No. Reason: the two methods have different signatures; This is a case of |
Paradigms → OOP → Inheritance →
Method overloading is when there are multiple methods with the same name but different type signatures. Overloading is used to indicate that multiple operations do similar things but take different parameters.
Type Signature: The type signature of an operation is the type sequence of the parameters. The return type and parameter names are not part of the type signature. However, the parameter order is significant.
Example:
| Method | Type Signature |
|---|---|
int add(int X, int Y) |
(int, int) |
void add(int A, int B) |
(int, int) |
void m(int X, double Y) |
(int, double) |
void m(double X, int Y) |
(double, int) |
In the case below, the calculate method is overloaded because the two methods have the same name but different type signatures (String) and
(int)
calculate(String): voidcalculate(int): void
Exercises
Which methods override?
Which of these methods override another method? A is the parent class. B inherits A.
- a
- b
- c
- d
- e
d
Explanation: Method overriding requires a method in a child class to use the same method name and same parameter sequence used by one of its ancestors
Can explain method overloading
Method overloading is when there are multiple methods with the same name but different type signatures. Overloading is used to indicate that multiple operations do similar things but take different parameters.
Type Signature: The type signature of an operation is the type sequence of the parameters. The return type and parameter names are not part of the type signature. However, the parameter order is significant.
Example:
| Method | Type Signature |
|---|---|
int add(int X, int Y) |
(int, int) |
void add(int A, int B) |
(int, int) |
void m(int X, double Y) |
(int, double) |
void m(double X, int Y) |
(double, int) |
In the case below, the calculate method is overloaded because the two methods have the same name but different type signatures (String) and (int)
calculate(String): voidcalculate(int): void
Can explain interfaces
An interface is a behavior specification i.e. a collection of
There are a number of situations in software engineering when it is important for disparate groups of programmers to agree to a "contract" that spells out how their software interacts. Each group should be able to write their code without any knowledge of how the other group's code is written. Generally speaking, interfaces are such contracts. --Oracle Docs on Java
Suppose SalariedStaff is an interface that contains two methods setSalary(int) and getSalary(). AcademicStaff can declare itself
as implementing the SalariedStaff interface, which means the AcademicStaff class must implement all the methods specified by the SalariedStaff interface i.e., setSalary(int) and getSalary().
A class implementing an interface results in an is-a relationship, just like in class inheritance.
In the example above, AcademicStaff is a SalariedStaff. An AcademicStaff object can be used anywhere a SalariedStaff object is expected e.g. SalariedStaff ss = new AcademicStaff().
Can implement abstract classes
Abstract Class: A class declared as an abstract class cannot be instantiated, but it can be subclassed.
You can declare a class as abstract when a class is merely a representation of commonalities among its subclasses in which case it does not make sense to instantiate objects of that class.
The Animal class that exist as a generalization of its subclasses Cat, Dog, Horse, Tiger etc. can be declared as
abstract because it does not make sense to instantiate an Animal object.
Abstract Method: An abstract method is a method signature without a method implementation.
The move method of the Animal class is likely to be an abstract method as it is not possible to implement a move method at the Animal class level to fit all subclasses because each animal type can move in a different way.
A class that has an abstract method becomes an abstract class because the class definition is incomplete (due to the missing method body) and it is not possible to create objects using an incomplete class definition.
Can explain substitutability
Every instance of a subclass is an instance of the superclass, but not vice-versa. As a result, inheritance allows substitutability : the ability to substitute a child class object where a parent class object is expected.
an Academic is an instance of a Staff, but a Staff is not necessarily an instance of an Academic. i.e. wherever an object of
the superclass is expected, it can be substituted by an object of any of its subclasses.
The following code is valid because an AcademicStaff object is substitutable as a Staff object.
Staff staff = new AcademicStaff (); // OK
But the following code is not valid because staff is declared as a Staff type and therefore its value may or may not be of type AcademicStaff, which is the type expected by variable academicStaff.
Staff staff;...AcademicStaff academicStaff = staff; // Not OK
Can explain dynamic and static binding
Dynamic Binding (
OOP → Inheritance → What
Paradigms → OOP → Inheritance →
Method overriding is when a sub-class changes the behavior inherited from the parent class by re-implementing the method. Overridden methods have the same name, same type signature, and same return type.
Consider the following case of EvaluationReport class inheriting the Report class:
Report methods |
EvaluationReport methods |
Overrides? |
|---|---|---|
print() |
print() |
Yes |
write(String) |
write(String) |
Yes |
read():String |
read(int):String |
No. Reason: the two methods have different signatures; This is a case of |
Paradigms → OOP → Inheritance →
Method overloading is when there are multiple methods with the same name but different type signatures. Overloading is used to indicate that multiple operations do similar things but take different parameters.
Type Signature: The type signature of an operation is the type sequence of the parameters. The return type and parameter names are not part of the type signature. However, the parameter order is significant.
Example:
| Method | Type Signature |
|---|---|
int add(int X, int Y) |
(int, int) |
void add(int A, int B) |
(int, int) |
void m(int X, double Y) |
(int, double) |
void m(double X, int Y) |
(double, int) |
In the case below, the calculate method is overloaded because the two methods have the same name but different type signatures (String) and (int)
calculate(String): voidcalculate(int): void
Exercises
Which methods override?
Which of these methods override another method? A is the parent class. B inherits A.
- a
- b
- c
- d
- e
d
Explanation: Method overriding requires a method in a child class to use the same method name and same parameter sequence used by one of its ancestors
Consider the code below. The declared type of s is Staff and it appears as if the adjustSalary(int) operation of the Staff class
is invoked.
void adjustSalary(int byPercent) { for (Staff s: staff) { s.adjustSalary(byPercent); }}
However, at runtime s can receive an object of any subclass of Staff. That means the adjustSalary(int) operation of the actual subclass object will be called. If the subclass does not override that operation,
the operation defined in the superclass (in this case, Staff class) will be called.
Static binding (aka early binding): When a method call is resolved at compile time.
In contrast,
Paradigms → OOP → Inheritance →
Method overloading is when there are multiple methods with the same name but different type signatures. Overloading is used to indicate that multiple operations do similar things but take different parameters.
Type Signature: The type signature of an operation is the type sequence of the parameters. The return type and parameter names are not part of the type signature. However, the parameter order is significant.
Example:
| Method | Type Signature |
|---|---|
int add(int X, int Y) |
(int, int) |
void add(int A, int B) |
(int, int) |
void m(int X, double Y) |
(int, double) |
void m(double X, int Y) |
(double, int) |
In the case below, the calculate method is overloaded because the two methods have the same name but different type signatures (String) and (int)
calculate(String): voidcalculate(int): void
Note how the constructor is overloaded in the class below. The method call new Account() is bound to the first constructor at compile time.
class Account { Account () { // Signature: () ... } Account (String name, String number, double balance) { // Signature: (String, String, double) ... }}
Similarly, the calcuateGrade method is overloaded in the code below and a method call calculateGrade("A1213232") is bound to the second implementation,
at compile time.
void calculateGrade (int[] averages) { ... }void calculateGrade (String matric) { ... }
Can explain OOP polymorphism
Polymorphism:
The ability of different objects to respond, each in its own way, to identical messages is called polymorphism. -- Object-Oriented Programming with Objective-C, Apple
Polymorphism allows you to write code targeting superclass objects, use that code on subclass objects, and achieve possibly different results based on the actual class of the object.
Assume classes Cat and Dog are both subclasses of the Animal class. You can write code targeting Animal objects and use that
code on Cat and Dog objects, achieving possibly different results based on whether it is a Cat object or a Dog object. Some examples:
- Declare an array of type
Animaland still be able to storeDogandCatobjects in it. - Define a method that takes an
Animalobject as a parameter and yet be able to passDogandCatobjects to it. - Call a method on a
Dogor aCatobject as if it is anAnimalobject (i.e., without knowing whether it is aDogobject or aCatobject) and get a different response from it based on its actual class e.g., call theAnimalclass' methodspeak()on objectaand get a"Meow"as the return value ifais aCatobject and"Woof"if it is aDogobject.
Polymorphism literally means "ability to take many forms".
Can explain how substitutability operation overriding, and dynamic binding relates to polymorphism
Three concepts combine to achieve polymorphism: substitutability, operation overriding, and dynamic binding.
- Substitutability: Because of substitutability, you can write code that expects object of a parent class and yet use that code with objects of child classes. That is how polymorphism is able to treat objects of different types as one type.
- Overriding: To get polymorphic behavior from an operation, the operation in the superclass needs to be overridden in each of the subclasses. That is how overriding allows objects of different subclasses to display different behaviors in response to the same method call.
- Dynamic binding: Calls to overridden methods are bound to the implementation of the actual object's class dynamically during the runtime. That is how the polymorphic code can call the method of the parent class and yet execute the implementation of the child class.
Exercises
Concepts related to polymorphism
Which one of these is least related to how OO programs achieve polymorphism?
(c)
Explanation: Operation overriding is the one that is related, not operation overloading.
Can answer frequently asked OOP questions
What’s the difference between a Class, an Abstract Class, and an Interface?
- An interface is a behavior specification with no implementation.
- A class is a behavior specification + implementation.
- An abstract class is a behavior specification + a possibly incomplete implementation.
How does overriding differ from overloading?
Overloading is used to indicate that multiple operations do similar things but take different parameters. Overloaded methods have the same method name but different method signatures and possibly different return types.
Overriding is when a sub-class redefines an operation using the same method name and the same type signature. Overridden methods have the same name, same method signature, and same return type.
Can combine some OOP concepts
...
Exercises
In the context of OOP, what is the relationship between abstraction and encapsulation?
Prerequisites
OOP: Objects: Encapsulation
OOP: Objects: Abstraction
Explanation: We can have abstraction without encapsulation. For example, we can think in terms of student entities when we code in C (a procedural language). But when we use a language that has encapsulation too (e.g., in Java/C++/C#), we can package all student related data and functions into one construct (i.e. a class). This makes the ‘student’ abstraction stronger because now we can not only think in terms of students, the program can perform actions using objects that represent student entities.
Which of these do not belong to four main OO principles?
Prerequisites
OOP: Objects: Abstraction
OOP: Objects: Encapsulation
OOP: Inheritance: Basic
OOP: Inheritance: Substitutability
OOP: Polymorphism: Introduction