IB/Group 4/Computer Science/Object-Oriented Programming

Object-Oriented Programming (OOP) is a way of designing programs and structuring your code. It is different from the functional programming paradigm which you might have used until now. The OOP paradigm allows you to define Objects that have specific behaviors in order to abstract and mimic "real life" behaviors. In OOP we focus mostly on the "what", meaning the functionalities of the Objects, rather than the "how", the algorithmic implementations of specific functionalities. Thus the design of programs will focus first on behaviors needed, to make sure the program structure is right, and then on the implementation details.

What is an object?
Objects represent a concept, an idea, or any entity in the physical world. For example, a player, a game board, a die, etc. These objects will have properties of their own. For example, a die can be rolled and give a number, but the board cannot. The interaction between objects via their properties and their relations allows us to better model complex problems in independent code structures.

In Java, objects are defined in classes using the  keyword. Here we created the  class. Objects consist of two things:


 * Attributes: The parameters of objects. For example, a user's name, user language, user subscription,...
 * Methods: The functions and behaviors of objects. For example, a user can greet someone, ask a question, make a reclamation,...

Let's add a  attribute and a   method to our "User" object.

Now, let's see how to create and use our object. However, before we get to that, we need to define a special method, called the constructor. The constructor method will allow us to create instances of our objects. An instance of a class means an actual object that has its own memory location and that can be used.

Constructor methods are called when we initialize a new instance of an object. They allow us to set initial values for our attributes.

Constructor methods always have the same name as our class name and cannot have a return type. Here is a demo: Note that all classes have constructors by default: if you do not create a class constructor yourself, Java creates one for you. However, in that case, you are no longer able to set initial values for object attributes. This means that we could create a User here, but we could not set its name upon instantiation.

We can also note the use of the keyword. The  keyword refers to the current object in a method or constructor. (The most common use of the  keyword is to eliminate the confusion between class attributes and parameters with the same name, for example when a class attribute is shadowed by a method or constructor parameter.)

Now let's instantiate our User object: In this code, we are not in the  class. We wrote our code in the  method, which acts as an entry point to your program for Java and is the method that is going to be executed when your program is run, inside the Main class.

You can also see that we used the  keyword to create our User instance,. This syntax is similar to what we would use when instantiating reference types in Java. Defining a class could thus be seen as writing your own, user-defined, reference type. The  after the   keyword is the call to the constructor method with the name parameter being "John" here.

After we instantiated our, we used its available method   with the dot notation.

If we compile both our  and   files and then run our compiled Main.java file, then we see the following result on our terminal:

To use an object or class it is necessary to instantiate the object first (unless using a static class). Instantiating a class means creating a location in memory for the object. The values contained inside an object will be individual to each instance of the object. Each instance of the class will usually have the same functions but these can behave differently based on the individual values of the attributes.

Accessor and mutator methods
In our previous example, we used the constructor method to pass a value,, to be set to our attribute  , in our   class.

But what if we want to modify that name later on? (Maybe we made a spelling mistake.) To easily modify attributes, we usually define accessor and mutator methods (these methods are also sometimes called getter and setter methods).

They look something like this: By convention, we usually define the accessor's method name with 'get' + the name of the attribute we want to get. Similarly, for defining the mutator's method name we use 'set' + the name of the attribute we want to change. However, if there is a naming that makes the code clearer to read and easier to understand, we can deviate from that naming convention.

We could use the accessor and mutator methods on our  class like so:  This would output: In OOP, methods such as constructors, accessors and mutators are the preferred way to modify attributes of an object. They allow for more flexibility than deleting and recreating an instance and they also allow better encapsulation, which we will see in the following sections.

Exercise

Imagine you want to code a digital clock app:
 * What attributes would the Clock object have?
 * What methods would the Clock object have?
 * Open an IDE and try to code this clock object.
 * Does a clock object already exist in the standard Java library?

Decomposing a problem into several objects
Decomposition in computer science, also known as factoring, refers to the process by which a complex problem or system is broken down into parts that are easier to conceive, understand, program, and maintain. Object-oriented decomposition breaks a large system down into progressively smaller classes or objects that are responsible for some part of the problem domain.

There isn't "one" method for achieving the best OOP structure ever for your problem, but there are design processes that can be applied to help. Most of these processes can be seen in Topic 1, such as iterative development, agile development, test-driven development, ...

Using UML to represent your objects and their relationships is also an essential part of the design process. (see below) In order to be able to develop solutions to complex problems we will need to define different objects during a project and these Objects will interact with each other.

Objects mostly have three kinds of relationships:
 * the "has-a" relationship, means that an attribute of a class will be an instance of another. For example, a Book object will have an Author object or a HighSchoolClass object will have Students and a Teacher.
 * the "is-a" relationship, also called Inheritance, means that one Object is a subcategory of another object. It is a more precise definition of an over-category. For example, a Student Object extends the Human Object, a Car Object extends the Vehicle Object or a Dog Object extends the Animal Object.
 * the "uses-a" relationship, means that one object will use an instance of a class during one of its methods. For example, a Student Object might use a Book object while reading, a Shelf Object might use a drill during building, and a Human Object might use a Swimsuit Object and Towel Object during swimming.

Let's see some code examples of these three relationships.

The "has-a" relationship
Let's use the example of a Book object that will have an Author object as an attribute. Let's first define our Author class: Now let's define our Book class: If we compile both our  and   and then run our   file (as it is the one that has the   method) we will get the following output:

Exercise: Try to define a "has-a" relationship between a HighSchoolClass Object, a Students Object, and a Teachers Object. ''Hint: you might want to define a Students Object that contains several Student objects. This is called an aggregate class (for Students).''

The "is-a" relationship
Let's use the example of the  class that extends the   class.

For that, let's define a very simple  class. This  class has one attribute   and one method. Now if we define the  class, as a subclass of   (because all students are humans) this means that the   class will have access to both the   attribute and the   method without having to redefine them. The  class is also allowed to have additional attributes or methods.

To express the "is-a" relationship from  to   we use the   keyword when defining the subclass.

So our  class would look like this: When we compile and then run our   code we get: Note that we could also have chosen to call our   method ,   instead. In that case, a  object will always execute the student version of the   method and not the   version. This is called overriding. We will study more aspects of Inheritance in the dedicated section. Exercise: Try to define a "is-a" relationship between an  class and a   class.

The "uses-a" relationship
Let's study an example of a  Object that is using a   object in one of its method. First, let's define the  class: The  Object is quite simple, it stores a book title and we have accessors and mutators around the book title and the page we are currently at.

Now let's define the  class. The  will have a method   that will use a   object to work. So now if we compile and run our  code we get the following output: But why is the   object an argument of the method   and not stored as an attribute? Well, the  is not an essential part of the , it does not define a property of the. It is used occasionally for a specific task, so it's better to pass it as an argument.

It is also interesting to note that the  is not very explicit in what it is doing. Defining a method  could have been easier to read and a better "clean code" practice here. Exercise: Try to define a "uses-a" relationship between a  class and a   class in a   method.

UML
The Unified Modeling Language (UML) is a graphical modeling language based on pictograms and visual elements. It is designed to be a standardized method of visualization in the fields of software development and object-oriented design.

UML was designed to support the software development process throughout all of its life cycle. Its thus provides lots of diverse diagram templates such as deployment diagrams, use-case diagram, timing diagram, etc..... The one we are interested in, for OOP and the IB diploma, is the class diagram. It describes the structure of a system by showing the system's classes, their attributes, methods, and the relationships among objects.

Let's look at the different graphical elements used in class diagrams.

The class element
In the diagram, classes are represented with boxes that contain three compartments:


 * The top compartment contains the name of the class. It is printed in bold and centered, and the first letter is capitalized.
 * The middle compartment contains the attributes of the class. They are left-aligned and the first letter is lowercase.
 * The bottom compartment contains the operations the class can execute. They are also left-aligned and the first letter is lowercase.

Visibility of elements
To specify the visibility of a class member (i.e. any attribute or method), these notations must be placed before the members' name: The above UML diagram is of class "Book", with two private attributes: "title" of type String and "currentPage" of type int, defaulting to value of 0. Two methods are part of the class, "turnPage" and "getTitle", both taking no parameters.

Relationships between objects
UML defines the following relationships:


 * Association: means that one class is using an instance of another class. It is a form of "has-a" relationship. You can recognise association when you see an attribute being an instance of another class. For example a Music object will have an instance of a Guitar Object as attribute so it can use the guitar in its methods to produce a music. It is depicted with a simple black arrow going out from the class that uses the other class.
 * Aggregation: means that one class has a collection of several instances of an other class. It is a form of "has-a" relationship. For example a Class will consist of several Student instances. Aggregation can be recognised when you have an attribute that is a collection of instances of another class. Aggregation is noted in UML with an open diamond towards the class that has the multiple instances of the other class.
 * Inheritance: means that a superclass/subclass relationship is happening. It is a form of "is-a" relationship. Refer to the section below to learn more about inheritance. It is depicted with a white arrow going pointing towards the superclass and originating from the subclass.
 * Dependency: means that one class depends on another for a specific action. It is a form of "uses-a" relationship. For example a Student object needs an instance of Swimsuit in order to go swimming. Dependency can be recognised in code as an instance of another class being used as a parameter of a method. It is depicted with a simple black arrow with a dashed line going out from the class that uses the other class.

Exercise: Draw the UML class diagram of the following project: https://home.uia.no/hallgeir/Java_Programmering/BokProsjekter/projects/chapter14/taxi-company-stage-one/. You can omit the test classes from your diagram.

Exercise: Write the java code for the following UML diagrams.

For example if you change, B, it affects how C, D and E works, implying that you have to spend time fixing them to work with the “new” B.
 * It increases maintenance overheads
 * Maintenance overheads refer to the changes that need to be made to the entire system if you make a change to a component.


 * char: smallest addressable unit of the machine that can contain basic character set. It is an integer type. Actual type can be either signed or unsigned depending on the implementation.
 * int: basic signed integer type. At least in the [−32767,+32767] range, thus at least 16 bits in size.
 * float: single precision floating-point type. Actual properties unspecified (except minimum limits), however on most systems this is the IEEE 754 single-precision binary floating-point format.
 * string: holds sequences of unsigned 16-bit (2-byte) code points that range in value from 0 through 65535. Each code point, or character code, represents a single Unicode character. A string can contain from 0 to approximately two billion (2 ^ 31) Unicode characters.

Encapsulation
Encapsulation is defined as the "process of wrapping code and data together into a single unit". But what does that mean ? In a practical manner, encapsulation is achieved by setting the right level of access to attributes and methods. You can see it as a protective shield for an object: we protect the inner mechanisms and only reveal certain methods that the public can use. This is the same as when you start your computer, the "on" button abstracts all the start up processes happening in the background that the user doesn't see. The end user doesn't care about the details of implementations and shouldn't be bothered with.

To achieve encapsulation we have the following access modifiers to our dispositions. These can be set for both attributes and methods and should be explicit, rather than using the default access modifier.


 * Private: most restrictive keyword; Can only be accessed within the declared class
 * Protected: When declared, can only be accessed by the subclasses in another package or any class within the member class
 * Public: Can be accessed from any other class. It is the least restrictive keyword.
 * Default: If you don't specify any access modifier then the code is only accessible to classes in the same package. If you didn't declare any package this means your code is only accessible in your current project.

In most cases, we will want to set the attributes private and the accessors and mutators public. (Indeed this allows for more control over the modifications done to attributes (no direct modifications) and helps with debugging, managing unwanted behaviors and cleaner readable code.)

Let's use our first  example to examine the behaviors of these access modifiers. Public attributes When compiling and running our   we get the following output: Having a   attribute means we can directly change the value of the attribute   from another class. Private attributes If we try to compile and run the same  but with the attribute   in   we get the following error: Indeed if an attribute is private then it means we can not modify it directly from another class. We would have to use public accessor and mutator methods if available. We can however still use  the attribute inside it's class, as we are doing in the   method. Private methods If we turn our  method private in   and try to call   in our   file we get the following error: Indeed if the   method is private then it means it can not be accessed by any classes outside itself. The only ways we could use a private method would be in another method inside the same class or if the  method was running from that class.

Public methods Public methods are accessible from external classes and behave "in the expected way";

Encapsulation provides several advantages:


 * It provides data hiding, this means that access to certain informations is controlled and restricted. That way the user (other classes) will only see available actions at its level and does not need to bother with implementation details. The data management of attributes is thus hidden away.
 * It provides better control over the data management as fewer unexpected behaviors can arise if user actions are limited.
 * It Increases usability by keeping data private and providing public well-defined service methods the role of the object becomes clear to other objects.
 * It provides flexibility as we can change access modifiers depending on our needs and depending on the use cases.
 * It helps us to have code that is easily testable through unit testing.
 * It make the code more reusable as we essentially care about what methods are present and less about the implementation. We can change an implementation of a method without changing the code the code structure. It promotes maintenance, as code changes can be made independently.

Inheritance
Inheritance is a concept where a subclass (also known as child class or derived class) inherits from a superclass (also known as parent class or base class). The subclass is a class that will describe a more precise kind of object that the superclass does. The subclass can have access to methods and attributes of the superclass.

Lets use our superclass  and subclass   from before. When we compile and then run our  code we get:

Here, the  class is a subclass of   (because all students are humans). Because of the access modifiers, the  class will have access to both the   attribute and the   method without having to redefine them here. Indeed a subclass does not inherit the  members of its parent class. Only  or   members are inherited. However, if the superclass has  or   methods for accessing its   attributes, these can also be used by the subclass.

The  class is also allowed to have additional attributes or methods. Here  has an additional   attribute and two additional methods:   and

To define a subclass we use the  keyword. The keyword is only used in the subclass and not in the superclass. Here

Constructors are not members of a class, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass. To achieve this we make use of the keyword. The  keyword allows us to access attributes, methods and constructors from the superclass. Here in our Student constructor we refer to Human's constructor by calling.

A subclass can also be superclass for another subclass. This is called multilevel inheritance. For example we could have: Student that extends Human that extends Mammal that extends Animal. Here Human would be the subclass for Mammal but the Human would also be the superclass for Student. In Java classes only support single inheritance so we can only extend one class at the time (we would write  and not  . To see that global inheritance pattern, UML diagrams are very useful.

A superclass can be extended by multiple classes. This is called hierarchical inheritance. For example the Human class can be extended by the Student class but the Human class could also be extended by the Teacher class at the same time. Again, to see that global inheritance pattern, UML diagrams are very useful.

Overriding
Overriding happens when we define an attribute or a method in the subclass, with the same name than in the superclass. If that happens then the attribute or method of the superclass is hidden and cannot be accessed by an instance of the subclass anymore.

For example if we had defined  as   instead in our   Class, then every time we call the   method on a   instance we will get a message with the name + the school of the student. From a  instance we would not be able to have a greeting message with the name of the student only, anymore. From a  instance however we would get the greeting message with the name only, when calling.

Overriding is useful when a subclass needs a more precise definition of a certain behavior than in the superclass.

Exercise: Rename the  method as   and then try calling this method from a Student instance and then form a Human instance. What happens ?

Casting
Since a Student object is also a Human object, a Student object can be used when a Human object is wanted. On the other hand a Human object can not be called instead of a Student Object. Nothing would prevent us from writing:  with   being a Student instance. The explicit casting is not even mandatory here. Casting from a subclass to a superclass is called upcasting.

Exercise: Try to implement Teacher class as a subclass of Human

The main advantage of inheritance is that is allows for code reusability. The code from the superclass doesn't need to be rewritten in the subclass, hence saving us a lot of time and avoiding code duplication and thus mistakes.

Overriding is also a big advantage as it provides modularity to cover more inheritance cases. Indeed details of superclasses can hidden to only focus on the current, more specific, behavior of the subclass. Method overriding is also known as runtime polymorphism.

Polymorphism
Polymorphism is a way of accessing multiple object of different types in the same way. To do this you make use of a polymorphic type that can be accessed in a way that also applies to all the other types of the objects. This is often used in combination with inheritance where multiple different child classes can be accessed as a parent class type and providing access to all features from the parent class or features that have been overloaded by the child class. Polymorphic child classes do not allow access to added features of the child class.


 * Same interface could be used for creating methods with different implementations
 * Reduces the volume of work in terms of distinguishing and handling various objects
 * Supports building extensible systems
 * Complete implementation can be replaced by using same method signatures

Libraries of objects can be imported to avoid "reinventing the wheel". Many common tasks that applications perform (such as sorting) already have well-tested libraries written to perform them. With permission, another developer's code can be shipped along yours to save development time. This also reduces the testing surface, as well-tested libraries are unlikely to have bugs.

Objected oriented programs tend to have a much larger filesize than other programs. This was especially important in earlier times, where storage was limited, or in embedded systems were storage is still very limited. Objected oriented programs tend to be slower than linear programs, as the computer needs to traverse different classes and understand the relationships between them. OO programming languages tend to have a steep learning curve. Finally, object oriented programs tend to take more effort to create, as they require careful planning and conceptualization.

Teams are set up to accomplish larger tasks as a group Advantages of the use of teams: Disadvantages of the use of teams:
 * More members means more ideas, including ideas that might not have come about without a team
 * The strengths of some can cover up the weaknesses of others
 * With more "manpower" to work on problems, larger problems and projects could be taken on
 * If not handled properly, the weaknesses of some members could undermine the group as a whole
 * Different styles of programming and working have to learn to coincide and work together
 * Communication among members becomes a priority for the team by necessity


 * If a single procedure is developed it can be reused multiple times without having to retype the code
 * Programs can be designed more easily and more effectively due to the divisions of the entire code into sectors because a small team deals with only a small part of the entire code
 * Modular programming allows many programmers to collaborate on the same application
 * Code is stored across multiple files; code is also short, simple and easier to understand
 * Scoping of variables can be easily controlled
 * When errors are localized to a subroutine or function, they can be easily identified

Program development
Class: A class is the blueprint from which individual objects are created.

Identifier: Identifiers are the name of variables, methods, classes, packages, and interfaces. They are a way of referring to specific things.

Primitive: A value that is predefined by the language and is named to a reserved keyword.

Method: A method is a part of a program that executes java code. It is not to be confused with a constructor method.

Accessor: An accessor method is a method that is used to obtain information about an object and is also used in order to access the data in that object

Mutator: A mutator method is a method that is used to set a value of a private field that cannot be publicly accessed.

Constructor: A constructor method is a method that creates one instance of a class

Signature: Refers to the method name and the number and type of its parameters. Return types and thrown exceptions are not considered part of the signature

Return value: It is the value or data type that is returned after a program has been run

Private: most restrictive keyword; Can only be accessed within the declared class

Protected: When declared, can only be accessed by the subclasses in another package or any class within the member class

Public: Can be accessed from any other class

Extends: This Java keyword is used when you want a class or object to inherit from another class or object.

Static: This keyword signifies that a member variable, or method, can be accessed without requiring an instantiation of the class to which it belongs. In examination questions the primitive types will be limited to int, long, double, char and Boolean.

Primitive data types are most commonly used to store simple values. They are also used as the building blocks of the more complex abstract data types.

Although String is not a primitive data type, it is considered a ‘basic’ type as it is used to store simple values. IF / ELSE

Boolean conditions, e.g. WHILE list.hasNextFOR loops

WHILE loops {{IB_Computer_Science/Statement|D.3.10|}Discuss the ethical and moral obligations of programmers.}}
 * reading from an array
 * moving data to/from the array
 * printing out selections from it… etc.
 * specialized text enablement
 * sorting behavior
 * date and time formatting
 * keyboard layouts
 * UTF-8 encoding
 * Use of common character sets among many platforms and languages, like UNICODE
 * Platform independent high level languages (like Java) enable code to run on many platforms
 * Adequate testing of products to prevent possibilities of commercial or other damage
 * Acknowledging the work of other programmers (to avoid plagiarism)
 * Open Source movement
 * Robotics and artificial intelligence


 * Adequate testing of products to prevent possibilities of commercial or other damage
 * Acknowledging the work of other programmers (to avoid plagiarism)
 * Open Source movement
 * Robotics and artificial intelligence