Thursday, November 19, 2009

SCJP 1.6 Study Guide: Object Orientation Part 1

Object Orientation

To be a Sun Certified Java Programmer, object-oriented concepts in Java should be second nature to you. In this section we will talk about the OO features of Java like encapsulation, inheritance, and polymorphism. We will continue our discussion in implementing interfaces, return type declarations and static variables and methods. We will also discuss topics like overloading/overriding, casting and coupling and cohesion. This is the second section of this series if you want to read the first section go here.

Encapsulation and Inheritance

Encapsulation. Encapsulation results to code flexibility and maintainability by hiding implementation details(instance variables) behind public interfaces(methods).

To implement encapsulation you must do the following:
  • Hide instance variables by using the private access modifier.
  • Create public methods to access private instance variables. This will ensure that users of your classes will go through the method where you can implement checks that will assure you that your classes will be used the right way. These methods are called getters and setters(some call them accessors and mutators). For these methods it is recommended to use the JavaBeans naming convention(getXxx and setXxx).
Example:
(No Encapsulation)
public class Person{
public double weight;
}
public class TestPerson{
public static void main(String[] args){
Person person = new Person();
person.weight = -1.0; // you probably don't want this to happen
}
}
(With Encapsulation)
public class Person{
private double weight;

// getter
public double getWeight(){
return weight;
}

// setter
public void setWeight(double weight){
if(weight > 0){
this.weight = weight; // better, right?
}
}
}
public class TestPerson{
public static void main(String[] args){
Person person = new Person();
person.weight = -1.0; // this will compile but
// will not change the value
// of weight
}
}
Inheritance. Inheritance as defined by Answers.com refers to the process of genetic transmission of characteristics from parents to offspring. That definition somehow mirrors what inheritance is in Java.

Inheritance in Java allows one class called the subclass to extend another class, the super class. Where the subclass by extending the super class inherits some or all of the super class' members(instance variables and instance methods) depending on the member's visibility.

You implement inheritance by using the extends keyword with the class declaration.

Example:
public class Person{
private String firstName;

public void setFirstName(String firstName){
this.firstName = firstName;
}

public String getFirstName(){
return firstName;
}
}
public class Student extends Person{}
public class TestStudent{
public static void main(String[] args){
Student student = new Student();

System.out.println(student.getFirstName());
// wait Student has no getFirstName()
// well, Student got it thru inheritance from Person
student.setFirstName("Bob");
System.out.println(student.getFirstName());
}
}
Running TestStudent results to:
null
Bob
A class can only extend one class. You cannot say:
public class Student extends Person, Animal{}
The above example will not compile because there's no such thing as multiple inheritance in Java, but you must know that every class that Java programmers create implicitly extends the Object class.

Example:
public class TestClass{}
public class TestTestClass{
public static void main(String[] args){
TestClass test = new TestClass();
System.out.println(test.toString());
// where did toString() come from?
// toString() returns a String representation
// of an object in this case
// a reference to the object test

// let's check with instanceof operator
if(test instanceof TestClass){
System.out.println("test is a TestClass");
// of course we declared it to be
// a type of TestClass
}

if(test instanceof Object){
System.out.println("test is an Object");
}
}
}
Running TestTestClass results to:
TestClass@addbf1
test is a TestClass
test is an Object
Inheritance is usually used for the following purposes:
  • Code reuse. Which is shown by our Person and Student class. We created a generic Person class with a firstName, getFirstName() and setFirstName() and then created a specialized Student class in which we need a firstName again but since the Person class already has them we just need to extend it and we'll be able to set and get the firstName of any Student object too.
  • Polymorphism. Polymorphism in Java allows any subclass of a superclass be treated as type of the superclass.
Example:
public abstract class Animal{
public abstract void cry();
}
public class Dog extends Animal{
public void cry(){
System.out.println("Aw..Awoo..");
}
}
public class Cat extends Animal{
public void cry(){
System.out.println("Me..Meowwww..");
}
}
public class Vet{
public void vaccinate(Animal animal){ // polymorphism in action
animal.cry();
}
}
public class TestVet{
public static void main(String[] args){
Dog dog = new Dog();
Cat cat = new Cat();
Vet vet = new Vet();

// polymorphism in action
vet.vaccinate(dog); // This will compile and run since
vet.vaccinate(cat); // Dog and Cat are subclasses of Animal
}
}
Running TestVet results to:
Aw..Awoo..
Me..Meowwww..
The example above is patterned from an example in Head First Java, 2nd Edition.

First, we've defined an abstract Animal class with abstract method cry(). Next we've defined Dog and Cat classes which extends Animal and both provided an implementation for the cry() method. We've then created a Vet class and defined a vaccinate() method which accepts an object of type Animal. We declared the method parameter for vaccinate() to be of type Animal so that we don't need to create several other vaccinate() methods each time we come up with a different class that extends the Animal class. We don't care what class is passed to the vaccinate() method as long as it can be treated as an Animal.

Observe that when we ran TestVet, the JVM still executed the cry() method of for the Dog and the Cat class. We'll discuss why this happened in the next post.

Polymorphism is implemented in interfaces as well, which means that a class can be considered a type of an interface if that class implements the interface.

Example:
public interface Rollable{
void roll();
}
public class Dog extends Animal implements Rollable{
public void cry(){
System.out.println("Aw..Awoo..");
}

public void roll(){
System.out.println("The dog is rolling...");
}
}
public class TestRollableDog{
public static void main(String[] args){
Dog dog = new Dog();

if(dog instanceof Rollable){
System.out.println("dog is a Rollable");
}
}
}
Running TestRollable results to:
dog is a Rollable
IS-A.For the exam, we need to be able to determine if classes demonstrates IS-A or HAS-A relationship.

The IS-A relationship is based on class inheritance and interface implementation. You can always test this relationship by using the instanceof operator.

Example:
public class Animal{}
public interface Rollable{}
public class Dog extends Animal implements Rollable
public class Shitzu extends Dog
Listing the relationships we have:
  • Shitzu extends Dog, which means Shitzu IS-A Dog
  • Dog extends Animal, so Dog IS-A Animal (we don't really care about grammar here.:D)
  • Dog implements Rollable, so Dog IS-A Rollable
  • Since Dog IS-A Animal and Shitzu IS-A Dog we can say that Shitzu IS-A Animal. This only shows that a class has an IS-A relationship with anything further up the inheritance tree.
  • Q: Can we say Shitzu IS-A Rollable?
HAS-A. In contrast with IS-A relationship, HAS-A relationship is based on usage/existence/possession instead of inheritance.

Example:
public class Person{}
public class Student extends Person{
private Course course;
}
public class Course{}
In the above example we can say that Student IS-A Person and at the same time Student HAS-A Course. As you might have observed, if class A is an instance variable of class B then class B HAS-A class A.

That's it for this part we will discuss polymorphism deeper with the next post.

0 comments:

Post a Comment