Chapter 6: Encapsulation
• Encapsulation hides implementation details behind an Interface or an API
• Encapsulated code has two features:
o Instance variables are hidden (Usually with private modifier)
o Getter and Setter methods are provided to give access to instance variables
Chapter 7: Inheritance
• Inheritance allows a class to be a subclass of a superclass and thereby inherit code and functionality of the superclass
• All classes are subclasses of Object and therefore they inherit Objects methods
• IS-A relationship is expressed with the keyword extends
• HAS-A means an instance of one class “has a” reference to an instance of another class
• Single, Multilevel, Multiple (Partial of course) and Hybrid are the types of inheritance
Chapter 8: Polymorphism
• Polymorphism means many forms
• A reference variable is always of a single, unchangeable type, but it can refer to a subtype object
• A single object can be referred to by reference variables of many different types, as long as they are the same type or a supertype of the object
• The reference variables type (not the objects type), determines which methods are called
• Polymorphic method invocations apply only to overridden instance methods
Overriding & Overloading:
• Methods can be both overridden and overloaded
• Constructors can only be overloaded
• Abstract methods must be overridden by the first concrete class (non abstract class)
• Overridden methods:
o Must have the same argument list
o Must have the same return type or a covariant return
o Must not have a more restrictive access modifier
o Must not throw new or broader checked exceptions
o May throw fewer or narrower checked exceptions or any unchecked exception
• Final methods cannot be overridden
• Only inherited methods may be overridden (private methods are not inherited)
• You can use super.OverriddenMethodName() to call the super class’s version of the method
• Overloading means reusing a method name
• Overloaded methods
o Must have different arguments list
o May have different return types (But you cannot overload a method by just changing the return type)
o May have different access modifiers
o May throw different exceptions
o Overloading is not Polymorphism
• Reference type determines which overloaded method will be used at compile time (In case you have overloaded a method that is available in the parent class)
Chapter 9: Reference Variable Casting
• There are two types of reference variable casting: downcasting and upcasting
• Downcasting: If you have a reference variable that refers to a subtype object, you can assign it to a reference variable of the subtype. You must make an explicit cast to do this, and the result is that you can access the subtype’s members with this new reference variable.
• Upcasting: You can assign a reference variable to a supertype reference variable explicitly or implicitly. This is an inherently safe operation because the assignment restricts the access capabilities of the new variable.
Chapter 10: Implementing an Interface
• When you implement an Interface, you are fulfilling its contract
• If you implement an interface you must provide concrete overriding for all methods defined in the interface
• If you don’t provide implementation for all methods, you must mark your class Abstract
• A single class can implement many interfaces
Chapter 11: Return Types
• Overloaded methods can change return types
• Overridden methods cannot change return types (Except in case of covariant returns)
• Object reference return types can accept null as a return value
• An array is a perfectly legal return type, both to declare and to return as a value
• For methods with primitive return types, any value that can be implicitly converted to the return type can be returned
• Nothing can be returned from a method that has the void modifier
• You can use the return keyword to get out of a method early but you cannot return anything from a void method and you cannot use an empty return in a non-void method
• Methods with an object reference return type, can return a subtype
• Methods with an interface return type, can return any implementer
Chapter 12: Constructors and Instantiation
• A Constructor is always invoked when a new object of a class is created
• Each superclass in an objects inheritance tree will have a constructor called
• Every class (Even an abstract class) has atleast one constructor
• Even if you don’t write a constructor explicitly, the compiler will add a default no-arg constructor to your class
• If you write a constructor that takes arguments, the compiler will not place a no-arg constructor in your class
• Constructors must have the same name as the class (Case Sensitive)
• Constructors don’t have a return type (If you see a return type, then it’s a method and not a constructor)
• Constructors can use any access modifier including private
• The default constructor is always the no-arg constructor
• The first statement of every constructor must be a call to either this() or super()
• You cannot have both this() and super() in the same constructor
• Constructors are never inherited, so they cannot be overridden
• A constructor can be directly invoked only by another constructor
• You cannot call a constructor explicitly
Chapter 13: Statics
• Use static methods to implement behavior that will not be affected by the state of any instances
• Use static variables to hold data that is class specific. There will be only one copy of a static variable irrespective of how many instances you make of a class
• All static members of a class belong to the class and not any instance
• A static method cannot access instance variables
• Static methods cannot be overridden
Chapter 14: Coupling and Cohesion
• Coupling refers to the degree to which one class knows about another class
• Loose coupling is a desirable state of having classes that are well encapsulated, minimize references to one another
• Tight coupling is undesirable
• Cohesion refers to the degree in which a class has a single, well defined role or responsibility
• High cohesion is a desirable state and low cohesion is undesirable
Previous Chapter: Chapter 14: Coupling and Cohesion
Next Chapter: Self Test Chapters 6 to 14
Topics Covered in the Blog - Synopsis
Showing posts with label Encapsulation. Show all posts
Showing posts with label Encapsulation. Show all posts
Wednesday, January 26, 2011
Chapter 14: Coupling and Cohesion
You would have heard or learnt a lot about coupling and cohesion when you learnt object oriented concepts or while learning other programming languages like c++. Let me tell you up front that, this chapter is going to be from the SCJP exam perspective and is going to cover concepts related to these two topics only from the exam point of you and not the overall dig deep into the topics. Frankly speaking, you’ll have very few questions about coupling and cohesion on the real exam.
Lets get started.
These two topics, coupling and cohesion, have to do with the quality of an OO design. In general, good OO design calls for loose coupling and shuns tight coupling, and good OO design calls for high cohesion, and shuns low cohesion. As with most OO design discussions, the goals for an application are
• Ease of creation
• Ease of maintenance
• Ease of enhancement
Coupling
Coupling is the degree to which one class knows about another class. If the only knowledge that class A has about class B, is what class B has exposed through its interface, then class A and class B are said to be loosely coupled. If, on the other hand, class A relies on parts of class B that are not part of class B’s interface, then the coupling between the classes is tighter. In other words, if A knows more than it should about the way in which B was implemented, then A and B are tightly coupled.
Using this second scenario, imagine what happens when class B is enhanced. It’s quite possible that the developer enhancing class B has no knowledge of class A, (why would he/she?) Class B’s developer ought to feel that any enhancements that don’t break the class’s interface should be safe, so she might change some non-interface parts of the class, which then causes class A to break.
At the far end of the coupling spectrum is the horrible situation in which class A knows non-API stuff about class B, and class B knows non-API stuff about class A. (This is REALLY BAD CODING). If either class is ever changed, there’s a chance that the other class will break. Let’s look at an obvious example of tight coupling, which has been enabled by poor encapsulation:
class CalculateTaxes {
float rate;
float doIndia() {
TaxRatesInIndia str = new TaxRatesInIndia();
rate = str.salesRate; // ouch
// this should be a method call:
// rate = str.getSalesTaxRates("CO");
// do stuff with rate
}
}
class TaxRatesInIndia {
public float salesRate; // should be private
public float adjustedSalesRate; // should be private
public float getSalesTaxRates(String region) {
salesRate = new CalculateTaxes().doIndia(); // ouch again!
// do country-based calculations
return adjustedSalesRate;
}
}
All large OO applications are a mix of many classes and interfaces working together. Ideally, all interactions between objects in an OO system should use the APIs, in other words, the contracts, of the objects’ respective classes. Theoretically, if all of the classes in an application have well-designed APIs, then it should be possible for all interclass interactions to use those APIs exclusively. If you make changes to the way one class behaves, in a loosely coupled environment, you shouldn't be getting surprise errors in other classes. As we discussed earlier in this chapter, an aspect of good class and API design is that classes should be well encapsulated.
The point here is that coupling is a somewhat subjective concept. Because of this, the SCJP exam will test you on really obvious examples of tight coupling only. So don't worry much about having to make design decisions about code.
Cohesion
While coupling has to do with how classes interact with each other, cohesion is all about how a single class is designed. The term cohesion is used to indicate the degree to which a class has a single, well-focused purpose. Keep in mind that cohesion too is a subjective concept. The more focused a class is, the higher its cohesiveness. The key benefit of high cohesion is that such classes are typically much easier to maintain (and less frequently changed) than classes with low cohesion. Another benefit of high cohesion is that classes with a well-focused purpose tend to be more reusable than other classes. Let’s take a look at a pseudocode example:
class SalesReport {
void connectToDb(){ }
void generateSalesReport() { }
void saveAsFile() { }
void print() { }
}
Now imagine your manager comes along and says, “Hey you know that accounting application we’re working on? The clients just decided that they’re also going to want to generate a revenue projection report, oh and they want to do some inventory reporting also. They do like our reporting features however, so make sure that all of these reports will let them choose a database, choose a printer, and save generated reports to data files...”
Rather than putting all the printing code into one report class, we probably would have been better off with the following design right from the start:
class SalesReport {
Options getReportingOptions() { }
void generateSalesReport(Options o) { }
}
class ConnectToDb {
DBconnection getDb() { }
}
class PrintStuff {
PrintOptions getPrintOptions() { }
}
class FileSaver {
SaveOptions getFileSaveOptions() { }
}
This design is much more cohesive. Instead of one class that does everything, we’ve broken the system into four main classes, each with a very specific, or cohesive, role. Because we’ve built these specialized, reusable classes, it’ll be much easier to write a new report, since we’ve already got the database connection class, the printing class, and the file saver class, and that means they can be reused by other classes that might want to print a report. Again, as in Coupling, you may not get too many questions about cohesion but if you are (un)lucky you may get one or two…
Previous Chapter: Chapter 13: Statics
Next Chapter: Quick Review: Chapters 6 to 14
Lets get started.
These two topics, coupling and cohesion, have to do with the quality of an OO design. In general, good OO design calls for loose coupling and shuns tight coupling, and good OO design calls for high cohesion, and shuns low cohesion. As with most OO design discussions, the goals for an application are
• Ease of creation
• Ease of maintenance
• Ease of enhancement
Coupling
Coupling is the degree to which one class knows about another class. If the only knowledge that class A has about class B, is what class B has exposed through its interface, then class A and class B are said to be loosely coupled. If, on the other hand, class A relies on parts of class B that are not part of class B’s interface, then the coupling between the classes is tighter. In other words, if A knows more than it should about the way in which B was implemented, then A and B are tightly coupled.
Using this second scenario, imagine what happens when class B is enhanced. It’s quite possible that the developer enhancing class B has no knowledge of class A, (why would he/she?) Class B’s developer ought to feel that any enhancements that don’t break the class’s interface should be safe, so she might change some non-interface parts of the class, which then causes class A to break.
At the far end of the coupling spectrum is the horrible situation in which class A knows non-API stuff about class B, and class B knows non-API stuff about class A. (This is REALLY BAD CODING). If either class is ever changed, there’s a chance that the other class will break. Let’s look at an obvious example of tight coupling, which has been enabled by poor encapsulation:
class CalculateTaxes {
float rate;
float doIndia() {
TaxRatesInIndia str = new TaxRatesInIndia();
rate = str.salesRate; // ouch
// this should be a method call:
// rate = str.getSalesTaxRates("CO");
// do stuff with rate
}
}
class TaxRatesInIndia {
public float salesRate; // should be private
public float adjustedSalesRate; // should be private
public float getSalesTaxRates(String region) {
salesRate = new CalculateTaxes().doIndia(); // ouch again!
// do country-based calculations
return adjustedSalesRate;
}
}
All large OO applications are a mix of many classes and interfaces working together. Ideally, all interactions between objects in an OO system should use the APIs, in other words, the contracts, of the objects’ respective classes. Theoretically, if all of the classes in an application have well-designed APIs, then it should be possible for all interclass interactions to use those APIs exclusively. If you make changes to the way one class behaves, in a loosely coupled environment, you shouldn't be getting surprise errors in other classes. As we discussed earlier in this chapter, an aspect of good class and API design is that classes should be well encapsulated.
The point here is that coupling is a somewhat subjective concept. Because of this, the SCJP exam will test you on really obvious examples of tight coupling only. So don't worry much about having to make design decisions about code.
Cohesion
While coupling has to do with how classes interact with each other, cohesion is all about how a single class is designed. The term cohesion is used to indicate the degree to which a class has a single, well-focused purpose. Keep in mind that cohesion too is a subjective concept. The more focused a class is, the higher its cohesiveness. The key benefit of high cohesion is that such classes are typically much easier to maintain (and less frequently changed) than classes with low cohesion. Another benefit of high cohesion is that classes with a well-focused purpose tend to be more reusable than other classes. Let’s take a look at a pseudocode example:
class SalesReport {
void connectToDb(){ }
void generateSalesReport() { }
void saveAsFile() { }
void print() { }
}
Now imagine your manager comes along and says, “Hey you know that accounting application we’re working on? The clients just decided that they’re also going to want to generate a revenue projection report, oh and they want to do some inventory reporting also. They do like our reporting features however, so make sure that all of these reports will let them choose a database, choose a printer, and save generated reports to data files...”
Rather than putting all the printing code into one report class, we probably would have been better off with the following design right from the start:
class SalesReport {
Options getReportingOptions() { }
void generateSalesReport(Options o) { }
}
class ConnectToDb {
DBconnection getDb() { }
}
class PrintStuff {
PrintOptions getPrintOptions() { }
}
class FileSaver {
SaveOptions getFileSaveOptions() { }
}
This design is much more cohesive. Instead of one class that does everything, we’ve broken the system into four main classes, each with a very specific, or cohesive, role. Because we’ve built these specialized, reusable classes, it’ll be much easier to write a new report, since we’ve already got the database connection class, the printing class, and the file saver class, and that means they can be reused by other classes that might want to print a report. Again, as in Coupling, you may not get too many questions about cohesion but if you are (un)lucky you may get one or two…
Previous Chapter: Chapter 13: Statics
Next Chapter: Quick Review: Chapters 6 to 14
Labels:
cohesion,
coupling,
Encapsulation,
inheritance,
Java,
loosely coupled,
SCJP,
SCJP Certification,
tightly coupled
| Reactions: |
Tuesday, January 4, 2011
Chapter 6: Object Oriented Concepts – Encapsulation
One of the key strengths of Java is that it is object oriented. In other words, everything in Java is an object. You might have heard me say this in the previous chapters and for sure I will say that at times in the future chapters as well because everything in Java is an object. There are a few important features/characteristics that Java exhibits by virtue of being object oriented. We will be covering them one by one in the following chapters.
Encapsulation:
Imagine that we both work for the same project and first you wrote the code for a class, and then I used your class in my program. Later on, you didn’t like the way the class behaved, because some of its instance variables were being set (by me from my code) to values you hadn’t anticipated. Their code brought out errors in your code. (Relax, I wont do that, dont worry.) Since, it is a Java program, so you should be able just to ship out a newer version of the class, which I could replace in my programs without changing any of my own code.
The above scenario highlights two of the promises or rather i should say benefits of Object Orientation (OO): flexibility and maintainability. But these benefits will not come automatically. You have to do something. You have to write your classes and code in a way that supports flexibility and maintainability. Just because Java supports OO concepts, it cannot write code for you. Can it?? For example, imagine if you made your class with public instance variables, and those other programmers were setting the instance variables directly, as the following code demonstrates:
public class BadExample {
public int size;
public int weight;
...
}
public class AnotherBadExample {
public static void main (String [] args) {
BadExample b = new BadExample ();
b.size = -5; // Legal but bad!!
}
}
Now go back the scenario we spoke about a paragraph ago. BadExample is your class and AnotherBadExample is my code. I have modified one of your variables in a way that it helps my code logic but that totally alters the way your class works. Now you are in trouble. How are you going to change your class in such a way that no one can alter your values directly (like what i have done in my code)? Your only choice is to write a method say setSize(int newVal) inside your class and then change the access modifier of the variable size to say, private. This will ensure that you handle instances when someone is trying to set a value to the size variable that you dont want and at the same time ensure that no one can access the size variable directly and mess with your code.
But, unfortunately, by doing that, you have broken my code. If I try to compile my AnotherBadExample class, i will get errors because the size variable is no longer visible for me.
How can we address this situation now? The best way is: not write such code where public variables are available for anyone and everyone to modify.
The ability to make changes in your code without breaking the code of all others who use your code is a key benefit of encapsulation. You should always hide implementation details. To elaborate, you must always have your variables as private and then have a set of public methods that others can use to access your variables. Since the methods are public anyone can access them, but since they are in your class you can ensure that the code works the way that is best for you. So in a situation that you want to alter your code, all you have to do is modify your methods. No one gets hurt because i am just using your method names in my code and the code inside your method doesnt bother me much.
If you want maintainability, flexibility, and extensibility (and I guess, you do), your design must include encapsulation. How do you do that?
• Keep instance variables protected (with an access modifier, mostly private).
• Make public accessor methods, and force calling code to use those methods rather than directly accessing the instance variable.
• For the methods, use the JavaBeans naming convention of set and get.
We call the access methods getters and setters although some prefer the fancier terms accessors and mutators. (Personally, I will be using the terms getters and setters) Regardless of what you want to call them, they’re methods that other programmers must go through in order to access your instance variables. They look simple, and you’ve probably been using them forever if you have been writing java code:
public class GoodExample {
// protect the instance variable only an instance of your class can access it
private int size;
// Provide public getters and setters
public int getSize() {
return size;
}
public void setSize(int newSize) {
size = newSize;
}
}
You are now probably mumbling, what benefit is it to have methods that do nothing and just set or get values. I would rather have a public variable. If you did that go to the first paragraph under Encapsulation and re-read the whole thing. And if you did not do that but are asking me, where is the validation code that we are supposed to have in the setSize() method to ensure no one modifies it to invalid values, my friend this is just an example class. I leave you to ponder about how the implementation needs to be. Atleast you wont end up on the receiving side of unexpected shocks because of someone like me coding along with you or worse !!!
Previous Chapter: Self Test - Chapters 1 to 5
Next Chapter: Chapter 7: Object Oriented Concepts - Inheritance
Encapsulation:
Imagine that we both work for the same project and first you wrote the code for a class, and then I used your class in my program. Later on, you didn’t like the way the class behaved, because some of its instance variables were being set (by me from my code) to values you hadn’t anticipated. Their code brought out errors in your code. (Relax, I wont do that, dont worry.) Since, it is a Java program, so you should be able just to ship out a newer version of the class, which I could replace in my programs without changing any of my own code.
The above scenario highlights two of the promises or rather i should say benefits of Object Orientation (OO): flexibility and maintainability. But these benefits will not come automatically. You have to do something. You have to write your classes and code in a way that supports flexibility and maintainability. Just because Java supports OO concepts, it cannot write code for you. Can it?? For example, imagine if you made your class with public instance variables, and those other programmers were setting the instance variables directly, as the following code demonstrates:
public class BadExample {
public int size;
public int weight;
...
}
public class AnotherBadExample {
public static void main (String [] args) {
BadExample b = new BadExample ();
b.size = -5; // Legal but bad!!
}
}
Now go back the scenario we spoke about a paragraph ago. BadExample is your class and AnotherBadExample is my code. I have modified one of your variables in a way that it helps my code logic but that totally alters the way your class works. Now you are in trouble. How are you going to change your class in such a way that no one can alter your values directly (like what i have done in my code)? Your only choice is to write a method say setSize(int newVal) inside your class and then change the access modifier of the variable size to say, private. This will ensure that you handle instances when someone is trying to set a value to the size variable that you dont want and at the same time ensure that no one can access the size variable directly and mess with your code.
But, unfortunately, by doing that, you have broken my code. If I try to compile my AnotherBadExample class, i will get errors because the size variable is no longer visible for me.
How can we address this situation now? The best way is: not write such code where public variables are available for anyone and everyone to modify.
The ability to make changes in your code without breaking the code of all others who use your code is a key benefit of encapsulation. You should always hide implementation details. To elaborate, you must always have your variables as private and then have a set of public methods that others can use to access your variables. Since the methods are public anyone can access them, but since they are in your class you can ensure that the code works the way that is best for you. So in a situation that you want to alter your code, all you have to do is modify your methods. No one gets hurt because i am just using your method names in my code and the code inside your method doesnt bother me much.
If you want maintainability, flexibility, and extensibility (and I guess, you do), your design must include encapsulation. How do you do that?
• Keep instance variables protected (with an access modifier, mostly private).
• Make public accessor methods, and force calling code to use those methods rather than directly accessing the instance variable.
• For the methods, use the JavaBeans naming convention of set
We call the access methods getters and setters although some prefer the fancier terms accessors and mutators. (Personally, I will be using the terms getters and setters) Regardless of what you want to call them, they’re methods that other programmers must go through in order to access your instance variables. They look simple, and you’ve probably been using them forever if you have been writing java code:
public class GoodExample {
// protect the instance variable only an instance of your class can access it
private int size;
// Provide public getters and setters
public int getSize() {
return size;
}
public void setSize(int newSize) {
size = newSize;
}
}
You are now probably mumbling, what benefit is it to have methods that do nothing and just set or get values. I would rather have a public variable. If you did that go to the first paragraph under Encapsulation and re-read the whole thing. And if you did not do that but are asking me, where is the validation code that we are supposed to have in the setSize() method to ensure no one modifies it to invalid values, my friend this is just an example class. I leave you to ponder about how the implementation needs to be. Atleast you wont end up on the receiving side of unexpected shocks because of someone like me coding along with you or worse !!!
Tip: In the exam watch out for code that appears to be asking about the behavior of a method when the problem is actually lack of encapsulation. Check out the below example:
class Test {
public int left = 9;
public int right = 3;
public void setLeft(int leftNum) {
left = leftNum;
right = leftNum/3;
}
// lots of complex test code here
}
Now let us say I ask you this question: Will the value of the variable right always be 1/3rd of the value in left? It sure looks that way doesnt it? And if you said Yes, the answer is No. See these variables they are public and they are not encapsulated like the example just a paragraph above. So a novice programmer like me could always set the value directly inside my code to spoil the party.
You must be cautious in order to spot such questions that are fairly easy and straightforward but confusing if you are in a hurry to finish the question.
Previous Chapter: Self Test - Chapters 1 to 5
Next Chapter: Chapter 7: Object Oriented Concepts - Inheritance
Labels:
Encapsulation,
encapsulation in java,
java encapsulation,
object orientation,
object oriented,
OO,
OO Java,
oops
| Reactions: |
Subscribe to:
Posts (Atom)
© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.
