Spaces:
Running
Running
| Encapsulation and internal integrity | |
| Before going into more detail about methods, let's look at one of the basic principles of object-oriented programming, namely encapsulation. | |
| The idea of encapsulation is to hide INFORMATION from the client that the CLIENT DOES NOT NEED to ACCESS directly. | |
| Why is encapsulation important? | |
| Let's go back to the earlier Student example: | |
| class Student { | |
| String name; | |
| String studentId; | |
| int studyPoints; | |
| public Student(String name, String studentId, int studyPoints) { | |
| this.name = name; | |
| this.studentId = studentId; | |
| this.studyPoints = studyPoints; | |
| } | |
| } | |
| When attribute values are not protected, the client is free to use them via an object reference, e.g. | |
| public class Testclass { | |
| public static void main(String[] args) { | |
| Student sam = new Student("Sam Student", "12345", 45); | |
| System.out.println("Student's name: " + sam.name); | |
| System.out.println("Student id: " + sam.studentId); | |
| System.out.println("Study points: " + sam.studyPoints); | |
| } | |
| } | |
| Program outputs: | |
| Student's name: Sam Student | |
| Student id: 12345 | |
| Study points: 45 | |
| VS | |
| However, a client may also (often ACCIDENTALLY) ASSIGN values to attributes that are not allowed for the | |
| meaning and rational operation of the object: | |
| Student sam = new Student("Sam Student", "12345", 45); | |
| sam.studyPoints -= 50; | |
| System.out.println(sam.studyPoints); | |
| Program outputs: | |
| -5 | |
| When an attribute of a object takes on an "illegal" value, the internal integrity of the object is broken. | |
| Thus, INTERNAL INTEGRITY means that the object is in such a state that all its attributes have an ALLOWED VALUE. | |
| ================= | |
| Observation methods | |
| Features can be hidden from the customer by making them private. | |
| This is done by adding the attribute 'private' to the feature definition. | |
| So let's make the Student attributes private by adding a 'private' attribute to their attributes: | |
| class Student { | |
| private String name; | |
| private String studentId; | |
| private int studyPoints; | |
| // The constructor is of course, public | |
| public Student(String name, String studentId, int studyPoints) { | |
| this.name = name; | |
| this.studentId = studentId; | |
| this.studyPoints = studyPoints; | |
| } | |
| } | |
| Now the client's attempt to use attributes is stopped by a TRANSLATION ERROR | |
| public class TestClass { | |
| public static void main(String[] args) { | |
| Student sam = new Student("Sam Student", "12345", 45); | |
| sam.studyPoints -= 50; | |
| } | |
| } | |
| Program throws an error: | |
| The field Student.studyPoints is not visible | |
| It is good practice to always define attributes as 'private'. | |
| But how can the client now access the object's data content? | |
| For this purpose, methods are written in the class that allow the client to observe and | |
| (if necessary) modify the data content. | |
| Let's start by defining an OBSERVATION METHOD for credits in the class: | |
| class Student { | |
| private String name; | |
| private String studentId; | |
| private int studyPoints; | |
| public Student(String name, String studentId, int studyPoints) { | |
| this.name = name; | |
| this.studentId = studentId; | |
| this.studyPoints = studyPoints; | |
| } | |
| // OBSERVATION METHOD for the study points | |
| public int getStudyPoints() { | |
| return this.studyPoints; | |
| } | |
| } | |
| The name of the method can be chosen freely; the course uses the getAttributeName() naming convention, | |
| which seems a bit funny in English-Mumbojumbo. | |
| This is because naming an observation method in this way is common practice in Java, | |
| and for example most Java editors use this format by default. | |
| Now the client can return the number of credits by calling the method: | |
| public class TestClass { | |
| public static void main(String[] args) { | |
| Student sam = new Student("Sam Student", "12345", 45); | |
| System.out.println("Study points: " + sam.getStudyPoints()); | |
| } | |
| } | |
| Program outputs: | |
| Study points: 45 | |
| Let's add other observation methods to the category: | |
| class Student { | |
| private String name; | |
| private String studentId; | |
| private int studyPoints; | |
| public Student(String name, String studentId, int studyPoints) { | |
| this.name = name; | |
| this.studentId = studentId; | |
| this.studyPoints = studyPoints; | |
| } | |
| // OBSERVATION METHODs for all attributes | |
| public String getName() { | |
| return name; | |
| } | |
| public int getStudyPoints() { | |
| return studyPoints; | |
| } | |
| public String getStudentId() { | |
| return studentId; | |
| } | |
| } | |
| Example on method calls: | |
| public class TestClass { | |
| public static void main(String[] args) { | |
| Student sam = new Student("Sam Student", "12345", 45); | |
| System.out.println("Student: " + sam.getName()); | |
| System.out.println("Study points: " + sam.getStudyPoints()); | |
| System.out.println("Student id: " + sam.getStudentId()); | |
| } | |
| } | |
| Program outputs: | |
| Student: Sam Student | |
| Study points: 45 | |
| Student id: 12345 | |
| When we compare the observation method with the methods we wrote earlier in the course, | |
| we notice one crucial difference: | |
| the METHOD that target an OBJECT DO NOT USE the attribute 'static'. | |