Download Understanding Encapsulation in OOP with Java: Classes, Objects, and Access and more Lecture notes Computer science in PDF only on Docsity!
Lecture 2 – Classes
- (^) What is Object Oriented Programming?
- (^) Object oriented Programming languages (OOP for short) include all
the features of structured programming and add more powerful ways
to organize algorithms and data structures.
- (^) There are three key features of OOP languages:
- (^) Encapsulation
- (^) Inheritance
- (^) Polymorphism
- (^) All of them are tied to the notion of a class
- (^) These two lectures focus on encapsulation through the use of classes
and objects - Object Based Programming.
Introduction
Classes
- (^) A class defines a set of variables ( attributes or data members ) that can be associated with the methods which act on an object with the object itself. data member methods
Classes
- (^) The following diagram explains the relationship between class and object.
Classes
- (^) A class contains data declarations and method declarations int x, y; char ch; Data declarations Method declarations
Classes
- (^) A class can be viewed as a blueprint of an object.
- (^) It is the model or pattern from which objects are created.
- (^) For example, the String class is used to define String objects.
- (^) Each String object contains specific characters (its state).
- (^) Each String object can perform services (behaviors) such as toUpperCase.
Objects
- (^) An object is created through the instantiation (or creation ) of a class.
- (^) You can look around you now and see many examples of real-world objects: your dog, your desk, your television set, your bicycle.
- (^) These real-world objects share two characteristics: they all have state ( data members ) and they all have behavior ( methods ). For example, cars have state (current gear, number of seats, four wheels, etc.) and behavior (braking, accelerating, slowing down, changing gears).
Classes and Objects s1:String "Programming" s2:String "Java" s3:String "ive-ty" String (class)
- (^) The String class can be used to define as many String objects as you like.
- (^) Its reusability is very high.
- (^) The String class is provided for us by the Java standard class library.
- (^) But we can also write our own classes that define specific objects that we need
class TestStringClass { public static void main(String s[]) { String s1 = new String("Programming"); String s2 = new String("Java"); String s3 = new String("ive-ty"); System.out.println(s1.toUpperCase()); System.out.println(s2.toUpperCase()); System.out.println(s3.toUpperCase()); } } Classes and Objects In this example, String is class. s1, s2 and s3 are the objects (or references to objects, precisely speaking). Each of them has different state but same behavior.
Example
class Employee {
int num; // data member (instance variable)
public int getNum() { // method
return num;
}
public void setNum(int newNum) { // method
num = newNum;
}
}
- (^) Let's define a very simple Employee class which has one data member and two methods.
Example
- (^) Thus when we create a new object we say we are instantiating the object. Each class exists only once in a program, but there can be many thousands of objects that are instances of that class.
- (^) To instantiate an object in Java we use the new operator. Here's how we'd create a new employee: Employee x = new Employee(); Class Name Object Name Class Name (Again!)
- (^) The instantiation can also be done in two lines: Employee x; x = new Employee();
Example
- (^) The members of an object are accessed using the. (dot) operator, as follows: Employee x = new Employee(); x.setNum( 12651 ); Object Name . (dot) Method Name
Example
- (^) We define a test driver class to test the Employee class: class Employee { private int num; public int getNum() { return num; } public void setNum(int newNum) { num = newNum; } } public class TestEmployee { public static void main(String[] args) { Employee emp1 = new Employee(); Employee emp2 = new Employee(); emp1.setNum(12651); emp2.setNum(36595); System.out.println("num of emp1 : " + emp1.getNum()); System.out.println("num of emp2 : " + emp2.getNum()); } } Sample Run > java TestEmployee num of emp1 : 12651 num of emp2 : 36595
Example Employee emp1 = new Employee(); Employee emp2 = new Employee(); Memory emp num : 0 getNum setNum emp num : 0 getNum setNum emp num : 0 getNum setNum
Example emp1.setNum(12651); emp2.setNum(36595); emp1.getNum() returns 12651 emp2.getNum() returns 36595
Note that the object name (emp1 and emp2) is simplified here. See
later slides for details
Memory emp num : 12651 getNum setNum emp num : 12651 getNum setNum emp num : 36595 getNum setNum emp num : 0 getNum setNum
- (^) Note when you compile the file Employee.java, you get two class files: Employee.class and TestEmployee.class.
- (^) You can save the above program (two class definitions) into one source file.
- (^) But if both of them are public, they must be defined in separate files.
- (^) Every Java class must extend another class
- (^) If class does not explicitly extend another class
- class implicitly extends Object So class Employee extends java.lang.Object is same as class Employee
Encapsulation
- (^) As you can see from the above diagram, an object's variables make up the centre or nucleus of the object. Methods surround and hide the object's nucleus from other objects in the program.
- (^) This is called encapsulation. emp num : 0 getNum setNum
Encapsulation
- (^) Member access modifiers
- (^) Control access to class’ instance variables and methods
- (^) public
- (^) Variables and methods accessible to other classes
- (^) private
- (^) Variables and methods not accessible to other classes
- (^) Can be accessed via
- (^) Accessor method (“ get ” method)
- (^) Allow clients to read private data
- (^) Mutator method (“ set ” method)
- (^) Allow clients to modify private data
javac PrintEmployee.java PrintEmployee.java:15: num has private access in PrivateDataEmployee emp.num = 12651; ^ 1 error class PrivateDataEmployee { private int num; public int getNum() { return num; } public void setNum(int newNum) { num = newNum; } } public class PrintEmployee { public static void main(String[] args) { PrivateDataEmployee emp = new PrivateDataEmployee(); emp.num = 12651; } }
A BAD Example class PublicDataEmployee { public int num; } class PrintPublic { public static void main(String[] args) { PublicDataEmployee emp1 = new PublicDataEmployee(); PublicDataEmployee emp2 = new PublicDataEmployee(); emp1.num = 12651; emp2.num = 36595; System.out.println("num of emp1 : " + emp1.num ); System.out.println("num of emp2 : " + emp2.num ); } }
java PrintPublic num of emp1 : 12651 num of emp2 : 36595
- (^) The following example shows an incorrect use of public data member.
A GOOD Example class PrivateDataEmployee { private int num; public int getNum() {return num;} public void setNum(int newNum) {num=newNum;} } class PrintPrivate { public static void main(String[] args) { PrivateDataEmployee emp1 = new PrivateDataEmployee(); PrivateDataEmployee emp2 = new PrivateDataEmployee(); emp1.setNum(12651); emp2.setNum(36595); System.out.println("num of emp1 : " + emp1.getNum() ); System.out.println("num of emp2 : " + emp2.getNum() ); } }
java PrintPrivate num of emp1 : 12651 Num of emp2 : 36595
- (^) The following shows how to fix the problem in the previous example.
Which is better?
- (^) PublicDataEmployee is shorter than PrivateDataEmployee.
- (^) Why do we say PrivateDataEmployee is better?
- (^) Suppose the company wants to make the employee number more meaningful by dividing the employee number into two parts, deptID and staffID , and the employee number is obtained by the formula deptID1000 + staffID*.
- (^) e.g. If the IT Dept has department ID 13 and the staff ID of Paul Leung is 228, then his employee number is 13228.
- (^) Consider the class PublicDataEmployee , it needs to be changed to class PublicDataEmployee { public int deptID; public int staffID; }
- (^) PrintEmployee1 cannot be compiled anymore. You have to change every occurrence of emp.num setting: emp1.deptID = 12; emp1.staffID = 651; emp2.deptID = 36; emp2.staffID = 595; and every occurrence of printing : emp1.deptID1000 + emp1.staffID emp2.deptID1000 + emp2.staffID**
class PrivateDataEmployee { private int deptID ; private int staffID ; public int getNum() { return deptID1000+staffID;* } public void setNum(int newNum) { deptID = newNum/1000; staffID = newNum%1000; } }
- (^) The class PrivateDataEmployee can be modified to meet the new requirement easily.
- We only need to change PrivateDataEmployee and all other classes that depend on it (e.g. PrintEmployee2) does not need to change.
- (^) The use of private data with set and get methods can also protect the data from invalid modification.
- e.g. To prevent setting of an employee number to a negative value, you can modify setNum as public void setNum(int newNum) { if (newNum < 0) System.out.println("Invalid emp. num."); else num = newNum; }
Benefits of Encapsulation
- (^) Encapsulation is used to hide unimportant implementation details from other objects.
- (^) Thus, the implementation details can change at any time without affecting other parts of the program.
- (^) Benefits of Encapsulation Modularity -- each object can be written and maintained independently of other objects. Also, an object can be easily passed around in the system. Information hiding -- an object can maintain private information and methods that can be changed at any time without affecting the other objects that depend on it