Difference between revisions of "Object Orientation"

From Suhrid.net Wiki
Jump to navigationJump to search
Line 304: Line 304:
 
* Methods can be overloaded with argument types that are in the same hierarchy.
 
* Methods can be overloaded with argument types that are in the same hierarchy.
 
* '''The decision to invoke a particular overloaded method is made at COMPILE time''', not at RUN time like polymorphic methods.
 
* '''The decision to invoke a particular overloaded method is made at COMPILE time''', not at RUN time like polymorphic methods.
 +
* See below: compiler will invoke overloaded method depending on the reference type.
  
 
<syntaxhighlight lang="java5">
 
<syntaxhighlight lang="java5">

Revision as of 05:37, 25 August 2011

Constructors

  • NO return type.
  • Can have all the access modifiers.
  • Can't be marked as abstract or final or static.

Class Modifiers

Regular Classes:

  • Access Modifiers: public and default only
  • Non access: strictfp, abstract and final only
  • Adding any other modifier will result in a compiler error.
  • A final class cannot be overriden (e.g. String)
  • An abstract class cannot be instantiated (e.g. DateFormat)

Class Members

  • Members can use all the access modifiers: public, private, default(package), protected
  • Private members are not inherited.
  • This means private members can be redeclared in subclasses.
  • Instance level variables cannot be synchronized, abstract, strictfp, native.

Protected

  • Protected is wider than package. Protected = package + subclasses.
  • For classes and subclasses in the same package protected works in exactly the same way as package(default).
  • For subclasses in other packages, protected members (both fields and methods) are only accessible through inheritance in the subclass.
  • The subclass in a different package cannot use a reference to super to access the protected member.
package pkg1;

public class Foo {
  protected String str = "Hello";
}

package pkg2;

public class Bar extends Foo {
  public void go() {
     Foo f = new Foo();
     String s = f.str; //Wont work ! Compiler error
     System.out.println(str); //Will work - through inheritance
  }
}

package pkg2;

public class Fubar {
   public void goo() {
        Bar b = new Bar();
        System.out.println(b.str); //wont work - str only accessible through inheritance
   }
}
  • One more example
package pkgA;

public class Animal {
	
	int count = 10;
	protected int secret = 42;
	
	void eat() {
		System.out.println("Animal Eat");
	}
	
	protected void mope() {
		System.out.println("Animal Moping");
	}
	
}

//Same package - different class

package pkgA;

public class Zoo {

	public static void main(String[] args) {
		Zoo z = new Zoo();
		z.go();
	}
	
	public void go() {
		Animal a = new Animal();
                //Package and protected are accessible
		a.eat();
		a.mope();
		System.out.printf("Package : %d %n", a.count);
		System.out.printf("Protected : %d %n", a.secret);
	}

}

//Same package - subclass

package pkgA;

public class Cat extends Animal {
	
	public static void main(String[] args) {
		Cat c = new Cat();
		c.catnap();
	}
	
	public void catnap() {
		System.out.println("Animal count :" + count); //package variable through inheritance
		System.out.println("Secret : " + secret); //protected variable through inheritance
                eat(); //package method through inheritance
		mope(); //protected method through inheritance

                Animal a = new Animal();
                //Access through super-class reference or super in all cases will work.
                a.count = 20;      
                super.secret = 18;
                super.eat();  
                a.mope(); 
	}
}


//Subclass in a different package

package pkgB;

import pkgA.Animal;

public class Dog extends Animal {

	public static void main(String[] args) {
		Dog d = new Dog();
		d.dawg();
	}
	
	public void dawg() {
                //None of the package level members will be accessible.

		System.out.println(secret); //This will work
                System.out.println(super.secret) // OR this will too
                Animal a = new Animal();
                System.out.println(a.secret); //This wont. Compile error.
                
                System.out.println(mope()); //OK
                System.out.println(super.mope()); //OK
                System.out.println(a.mope()); //NO. Compiler error.

	}
}

Abstract Methods

As they go against the logic of overriding :

  • abstract methods cannot be static.
  • abstract methods cannot be private.

Overriding

  • Polymorphic method invocations apply ONLY to instance methods.
  • The argument list for the overriding method must EXACTLY match that of the overriden method. Covariant arguments wont work! If arguments dont match, then the methods will overload.
  • Example:
class Masher {
	
	public void mash(Object o) {
		System.out.println("Masher.mash");
	}
	
}

class Jaws extends Masher {
	
	public void mash(String o) { //Overloads not Overrides the superclass method
		System.out.println("Jaws.mash");
	}
}

public class Override {

	public static void main(String[] args) {
		Masher m = new Jaws();
		m.mash("Hello"); //Will print Masher.mash
	}
	
}
  • The return type must be the same or a subtype (Covariant return) of the superclass method.
  • If the return types are not the same and arguments are the same - then this will be a name clash and the code wont compile.
  • Example:
interface Moveable {
	
	Number moveIt();
	
}

class Bike implements Moveable {
	
	public Integer moveIt() {
		return new Integer(42);
	}
	
}
  • Access level CANT be more restrictive but CAN be less restrictive.
  • Overriding method can throw ANY runtime exception regardless of what superclass method declares.
  • Overriding method cannot throw checked exceptions that are NEWER or BROADER than superclass method.
  • Overriding method can throw narrower or fewer checked exceptions.
  • It also need NOT redeclare any exceptions (checked or unchecked) from the superclass.


class Handler {
	
	public void handle() throws IOException {
		System.out.println("Handler.handle()");
	}
	
	public void handleIt() throws NumberFormatException {
		System.out.println("Handler.handleIt()");
	}
	
	public void handleMe() {
		System.out.println("Handler.handleMe()");
	}
}

class FileHandler extends Handler {
	
	public void handle() { //OK need not redeclare checked exception
		System.out.println("FileHandler.handle()");
	}
	
	public void handleIt() { //OK need not redeclare unchecked exception
		System.out.println("FileHandler.handleIt()");
	}
	
	public void handleMe() throws IllegalArgumentException { //OK can declare new unchecked exception
		System.out.println("Handler.handleMe()");
	}
}


class Handler {
	
	public void handle() throws IOException {
		System.out.println("Handler.handle()");
	}
	
	public void handleIt() throws InterruptedException {
		System.out.println("Handler.handleIt()");
	}
	
	public void handleMe() {
		System.out.println("Handler.handleMe()");
	}
}

class FileHandler extends Handler {
	
	public void handle() throws FileNotFoundException { //OK, narrower checked exception can be declared to be thrown
		System.out.println("FileHandler.handle()");
	}
	
	public void handleIt() throws Exception { //NOT OK, broader checked Exception being declared
		System.out.println("FileHandler.handleIt()");
	}
	
	public void handleMe() throws UnknownHostException  { //NOT OK, newer checked exception being declared
		System.out.println("Handler.handleMe()");
	}
}

Overloading

  • Overloaded methods differ only in argument list, no other restrictions.
  • Methods can be overloaded with argument types that are in the same hierarchy.
  • The decision to invoke a particular overloaded method is made at COMPILE time, not at RUN time like polymorphic methods.
  • See below: compiler will invoke overloaded method depending on the reference type.
class Gadget {
}

class Phone extends Gadget {
}

public class Overlord {

	public static void main(String[] args) {
		new Overlord().go();
	}
	
	void go() {
		Gadget g = new Gadget();
		Phone p = new Phone();
		Gadget gp = new Phone();
		
		foo(g); //Prints: Gadget
		foo(p); //Prints: Phone
		foo(gp);//Prints: Gadget
		
	}
	
	void foo(Gadget g) {
		System.out.println("Gadget");
	}
	
	void foo(Phone p) {
		System.out.println("Phone");
	}

}