Logout

D.2 Features of OOP (4 hours)

Students should be able to describe the features of OOP that distinguish it from other approaches to computer programming.

______________________________________________

 

Intro to OOP - Three Super Powers

There are many different ways of approaching programming, and each has its advantages and rationales. Functional programming and procedural programming are two other approaches you will often hear of. The main reason that OOP has risen to the fore in the past couple of decades is that it results, for a variety of reasons, in more stable, bug free code.

The stability and utility of Object Oriented Programming really comes down to three main concepts. And when compared to other ways of programming, they really do seem like superpowers:

Encapsulation - This makes our OOP superhero impenetrable to outside threats, like the Avengers collectively putting their shields up to protect Earth from Thanos.

Inheritance - In the same way that Wonder Woman and Donna Troy have inherited powers from their mother Hippolyta, and indeed from Zeus himself, classes in OOP programming are able to use strengths that come from further up an inheritance hierarchy, and in doing so they avoid the problems that can come from duplication.

Polymorphism - Just like with The Hulk/Bruce Banner, our OOP superhero methods can take on very different forms, depending on their context, adding a great degree of flexibility to the operation of programs.

______________________________________________

 


D.2.1

Define the term encapsulation.

 

Teaching Note:

Data and actions are limited to the object in which they are defined.

 

Sample Question:

Define the term encapsulation.


sdfsdfsf

JSR Notes:

Encapsulation Preface - Java .class Files

To totally understand a few of the things coming up in the following notes, you should have a bit of insight into the way OOP files are passed around to different programmers to be used. Here are the three main files types used and developed when coding in Java:

.java file - the actual text file that programmers work on (like the ones we work on in IntelliJ). If you sent this to another programmer, they can directly open it up and work on it.

.class file - the partially compiled file. When sent to another programmer, they can use the file (just like we use System or Scanner etc. classes) but they cannot open it and edit it. (Though, for the record, it actually can be de-compiled with a hack, but the whole point of OOP is it is not intended to be.)

It is this file which is most often shared among programmers and programming teams.

.jar file - this is the single compressed file we make when we are ready for our project to be used/sold as a stand alone app.

Above: An IntelliJ IDEA Project Structure - note the .java file, its associate .class file, and the overall .jar file

Above: A .java file - this is editable by anyone.

 

Above: The associated .class file - not editable in this form.

 

OOP Super Power # 1: Encapsulation

If we can’t protect the Earth, you can be damned well sure we'll avenge it.” - Tony Stark (With OOP encapsulation, no avenging needed!)

General Definition

One of the primary concepts of OOP is that both the attributes of a class and the methods that act upon them are together, "encapsulated". This implies that they are both together, and are protected.

The only way that attributes can be worked with by any other class is via the public interface of those methods. The methods control/manage the way that the attributes can be worked with. In this way, the programmer of a particular class has complete control over how data is worked with.

Encapsulated Against What?

The reasons that we don't want attributes to be altered from other classes are many. One reason is to protect security in the conventional sense; i.e. to protect money and information from being altered/accessed inappropriately. For example, if a class keeps track of the amount of money you have in the bank, the bank wouldn't want you to be able to hack into the data regarding your balance, as you could make this any value you wish. And though encapsulation does help security in this sense, it is used more generally to make programs more secure as in the stability sense. Encapsulation helps programs maintain the integrity of how their attributes are supposed to be handled.

Ultimately it is the programmer him/herself of particular code who knows best how the attributes in that code could/should be worked with. They know intimately the sorts of things that need to be avoided so that the data is not corrupted, compromised or rendered either problematic or useless. Compare this to the situation where the data in one class can be altered anyway another class chooses. We can assume that the programmers within a certain company or organization are not trying to sabotage each other's classes/programs, but it is much easier for them make mistakes when allowed to directly use the attributes of other colleague's code. There are just too many exceptional cases which need to be considered, and the author him/herself of each individual piece of code is best placed to handle these.


Protection...

Encapsulation means the "protection" of the data attributes of a class, so that objects of that class can only be used in ways that the programmer of that class permits.

This is done by keeping the data attributes themselves private, and only making available to other classes certain public methods which work with the data in specific, controlled ways. And further, it is only the signature of the methods which is publicly visible and accessible (i.e. only the method name, its return type and required parameters). The actual implementation of all methods (both public and private) are hidden from the other classes which use them.

So when encapsulation principles are followed, the using class cannot directly access attributes, and when it uses the public methods of the other class, it can't see or manipulate the contents of the method. It can only see what is referred to as the public interface, which is the method name, it's parameter list (number and kind of parameters) and return type.

...Via Grouping/Association

In some respects you could say that the grouping of attributes and methods that work on them is incidental - of course we group in this way. And for sure it's less the grouping than the protection within the groups that is most important. Never-the-less, the grouping, in-and-of itself offers its own distinct advantages, like easier testing and faster development, by splitting a big job into smaller, discrete, testable parts that can be worked on by various teams at the same time.

 

Java and Encapsulation

The Java keywords which enable encapsulation are mainly: private, and public, (though protected can also be useful).

private allows only access from within the class. So attributes are "protected" by being made private.

public allows all other classes access, so the methods which will be available to all other classes are made public. Do note that there may indeed be many methods which are private, which means they can only be used by other methods within that class. Such private methods are often referred to as "helper" methods.

(protected allows only other classes in the same package to have access. It is usually methods which are protected rather than attributes.)


Private Attributes

The Java reserve word private keeps data attributes (and some methods also) from being visible and accessible outside of the class in which they are defined. For example:


private double checkingAccountBalance;

Public Methods - but it's the Header only that is public

Even when a method is designated public (with the public reserve word), only it's header, i.e. it's signature that is visible to other classes.

So in a template class itself, which implements encapsulation, none of the body of the method can be seen by the using class. The only thing from the encapsulated method adjustCkBalance (in the class below) that the using class would see - via the documentation or the IDE - would be the method name, parameter list and return type:

And note that in the class below, since the checkingAccountBalance attribute is private, you could not directly do the following:

joesBankAccount.checkingAccountBalance += 1000000;
//ERROR - NOT POSSIBLE - checkingAccountBalance is a private attribute, not a public method intended to return the amount.

1    package forbankaccountexample; 
2     
3    public class BankAccount { 
4     
5        private double checkingAccountBalance = -999; 
6     
7     
8        public String adjustCkBalance(String pw, double amt) { 
9            String returnString = "not set yet"; 
10           if (pw.equals("!asdf@#$sdfLJk")) { 
11               if (amt < 0 && amt < checkingAccountBalance) { 
12                   returnString = "Sorry, withdraw amount is less than current balance."; 
13               } else { 
14                   checkingAccountBalance += amt; 
15               } 
16           } 
17           else{ 
18                   returnString = "Sorry, wrong password."; 
19           }return "Your new balance is " + checkingAccountBalance; 
20       } 
21   } 
 

_________________________________________


Advantages of Encapsulation

Refer to D.2.4 for the reasons all of this encapsulation is a good idea. (But - spoiler alert! - in the example above, the user class would not be able to directly withdraw or add money to the account, nor would the user class be able to see the password in the body of the method, to take an obvious advantage.)

 

Full Encapsulation Example

(Adapted from a past paper question.)

The problem with trying to explain encapsulation as an introduction to OOP is that encapsulation in many ways is every part of OOP except for inheritance and polymorphism - or put another way, encapsulation **is** OOP; it is grouping attributes with the methods that work on those attributes. So to see a full example, at least one which is useful in a "protection of attributes" sort of way, you pretty well have to see a ***full*** example. So here you go, a FULL OOP example. (The only things missing are inheritance and polymorphism.)

1    public class BookLoan { 
2        private int bookID; 
3        private String bookTitle; 
4        static int numBooksLoaned = 0; 
5     
6        //Constructors 
7        public BookLoan(){ 
8     
9        } 
10    
11       public BookLoan(int bookID, String bookTitle){ 
12           this.bookID = bookID; 
13           this.bookTitle = bookTitle; 
14           numBooksLoaned = numBooksLoaned ++; 
15       } 
16    
17       //"Gets", i.e. Accessor Methods 
18       public int getBookID(){ 
19           return this.bookID; 
20       } 
21    
22       public String getBookTitle(){ 
23           return this.bookTitle; 
24       } 
25    
26       //"Sets" 
27       public void setBookID(int id){ 
28           this.bookID = id; 
29       } 
30    
31       public void setBookTitle(String title){ 
32           this.bookTitle = title; 
33       } 
34   } 
35   

1    import java.util.ArrayList; 
2     
3    public class Student { 
4        private String studentName = "not set yet"; 
5        private int grade = -999; 
6        private boolean isIBDiploma = false; 
7        private ArrayList<BookLoan> bookLoans = new ArrayList<BookLoan>(); 
8        //so an example of aggregation; Student objects have BookLoans 
9     
10       //Constructors 
11       public Student(){ 
12    
13       } 
14    
15       public Student(String name, int grade){ 
16           studentName = name; 
17           this.grade = grade; 
18       } 
19    
20       public Student(String name, int grade, boolean isIBDiploma){ 
21           studentName = name; 
22           this.grade = grade; 
23           this.isIBDiploma = isIBDiploma; 
24       } 
25    
26       //THE FOLLOWING ARE ALL EXAMPLES OF THE "GROUPING/ASSOCIATION" 
27       //PART OF ENCAPSULATION - ALL OF THE METHODS THAT WORK WITH 
28       //THE ABOVE ATTRIBUTES ARE GROUPED HERE IN THIS CLASS 
29       //PARTICULARLY NOTE THE addLoan() METHOD BELOW... 
30    
31       //"Gets", i.e. Accessor Methods 
32       public String getStudentName() { 
33           return studentName; 
34       } 
35    
36       public int getGrade() { 
37           return grade; 
38       } 
39    
40       public ArrayList<BookLoan> getBookLoans(){ 
41           return bookLoans; 
42       } 
43    
44       public boolean isIBDiploma() { 
45           return isIBDiploma; 
46       } 
47    
48       //"Sets" 
49       public void setGrade(int grade){ 
50           this.grade = grade; 
51       } 
52    
53       public void setIBDiploma(boolean isIBDiploma){ 
54           this.isIBDiploma = isIBDiploma; 
55       } 
56    
57       //Other "Modifier" Methods 
58    
59       //... SO NEXT IS THE MOST IMPORTANT METHOD TO BE "GROUPED/ASSOCIATED" 
60       //WITH THE DATA ATTRIBUTES ABOVE. ONLY THIS METHOD CAN DETERMINE 
61       //WHETHER OR NOT ANOTHER BOOK CAN BE LOANED. AND THE IMPLEMENTATION 
62       //OF THAT IS ALL HIDDEN TO OTHER CLASSES. THE ONLY THING THAT THEY 
63       //CAN SEE IS THE PUBLIC HEADER BELOW. 
64    
65       public void addLoan(BookLoan newLoan){ 
66           if(bookLoans.size() > 0 && (this.grade < 11 || !isIBDiploma)){ 
67               System.out.println("Sorry you cannot take out another book"); 
68               if(this.grade < 11){ 
69                   System.out.println("because of your grade level.\n");
70               }
71               else{\
72                   System.out.println("even though you are grade 11 or 12, because" + 
73                           " you are not a full IB diploma student.\n"); 
74               } 
75           } 
76           else{ 
77               bookLoans.add(newLoan); 
78           } 
79    
80       } 
81   } 
82   

1    public class MainClass { 
2        public static void main(String[] args) { 
3     
4            Student[] borrowers = new Student[2000]; 
5            //(BTW, note the use of an array instead of an ArrayList, so lots of elements wasted 
6            //here, since there are only three students created, but 2000 elements made.) 
7     
8            Student zangChi = new Student("Zan Chi", 11, true); 
9            zangChi.addLoan(new BookLoan(345, "The Animals")); 
10           zangChi.addLoan(new BookLoan(678, "War and Peace")); 
11           //OK, since a book already on loan, but in grade 11, and is IBDiploma student. 
12           borrowers[0] = zangChi; 
13    
14           Student SooYongKim = new Student("Soo Yong Kim", 10); 
15           SooYongKim.addLoan(new BookLoan(1234, "The Odyssey")); 
16           SooYongKim.addLoan(new BookLoan(56645, "Don Quixote")); 
17           //NOT OK, GRADE 10 AND ALREADY WITH A BOOK ON LOAN. 
18    
19           //------->>>> SO THIS IS AN EXAMPLE OF THE "PROTECTION" PART OF ENCAPSULATION 
20           //DOING ITS JOB; THIS MainClass PROGRAM CANNOT DO ANYTHING TO TAKE OUT ANY 
21           //MORE BOOKS FOR THIS STUDENT; NOTHING **HERE** CAN BE DONE TO CHANGE THAT. 
22           //IT IS ALL CONTROLLED BACK IN THE HIDDEN PART OF addLoan().
22  
23           borrowers[1] = SooYongKim; 
24    
25           Student JoeNguyen = new Student("Joe Nguyen", 12, false); 
26           JoeNguyen.addLoan(new BookLoan(23423, "The Ocean")); 
27           JoeNguyen.addLoan(new BookLoan(75675, "Love in the Time of Cholera")); 
28           //Not OK, grade 11 and already a book on loan, and not IBDiploma student. 
29           borrowers[2] = JoeNguyen; 
30    
31    
32           borrowers[1].addLoan(new BookLoan(8778, "Wuthering Heights")); 
33           //Not OK, grade 10 and still a book on loan. 
34           borrowers[0].addLoan(new BookLoan(868, "The Spooks")); 
35           //OK, since a book already on loan, but in grade 11, and is IBDiploma student. 
36    
37    
38    
39    
40           System.out.println("----------------"); 
41           System.out.println(borrowers[0].getStudentName() + ":"); 
42           for(int i = 0; i < borrowers[0].getBookLoans().size(); i++){ 
43               System.out.println(borrowers[0].getBookLoans().get(i).getBookTitle()); 
44           } 
45    
46           System.out.println("----------------"); 
47           System.out.println(borrowers[1].getStudentName() + ":"); 
48           for(int i = 0; i < borrowers[1].getBookLoans().size(); i++){ 
49               //Do note that the size of the arraylist is 1, but this will still work. 
50               System.out.println(borrowers[1].getBookLoans().get(i).getBookTitle()); 
51           } 
52    
53           System.out.println("----------------"); 
54           System.out.println(borrowers[2].getStudentName() + ":"); 
55           for(int i = 0; i < borrowers[2].getBookLoans().size(); i++){ 
56               System.out.println(borrowers[2].getBookLoans().get(i).getBookTitle()); 
57           } 
58       } 
59   } 
60   

OUTPUT

Sorry you cannot take out another book
because of your grade level.

Sorry you cannot take out another book
even though you are grade 11 or 12, because you are not a full IB diploma student.

Sorry you cannot take out another book
because of your grade level.

----------------
Zang Chi:
The Animals
War and Peace
The Spooks
----------------
Soo Yong Kim:
The Odyssey
----------------
Joe Nguyen:
The Ocean

(Here is a link to the above IntelliJ IDEA project.)

 

Stability and Reliability of Programs

It is important to note, though hard to show without the aid of much more complex programs, that the main thing encapsulation protects against is poor programming choices with code that a programmer may not be familiar enough with.

So it's not so much keeping a user from using a program a certain way, for instance changing the number of books that can be loaned by a student, or withdrawing money from a bank account directly. Rather it's acknowledging the point that the original programmer/programming team knows all the ins and outs and peculiarities of its classes much, much better than any other programmer/team simply using those classes.

So the programmers using those classes should not be able to go in willy-nilly and change things. Sure, if they really took their time and knew their stuff, they may not make any errors. But OOP encapsulation principles ensures that this risk is not taken. Via encapsulation, the receiving programmer/team simply cannot dig inside and edit unfamiliar code - they are not permitted. Yet they are perfectly welcome to use those public method in the controlled ways which are permitted.

In "the olden days", pre-OOP, such digging around in other people's code was allowed, and it caused many stability and reliability problems. So it's the improved stability and reliability of programs which is the actual real benefit of OOP encapsulation.

 

In Summary, Back to the Assessment Statement:
Define the term encapsulation.

Encapsulation is the OOP practice of protecting of data by grouping data attributes and their associated methods together, and making the attributes themselves private. The attributes can only be accessed indirectly through public accessor methods, which work with the data in safe, controlled ways. This makes programs much more reliable.