Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Tuesday, 8 March 2016

Java and Ruby Inheritance Comparison

Following is a Ruby Program. This is heavily commented with reference to Java and Ruby both.
class A
  def methoda_public
    puts "Hello from methoda_public self=#{self}"
  end

  def methoda_private
    puts "Hello from methoda_private self=#{self}"
  end

  def methoda_protected
    puts "Hello from methoda_protected self=#{self}"
  end

    # 1) Java => class methods are defined using static keyword. instances can access class methods in Java.
    # 2) Ruby => class methods are actually singleton methods of class itself. (in Ruby a class is an object itself.). class methods are actually defined in
               # singleton class of "class object" and hence called as singleton methods. Only that object can call singleton method on which it is defined and none other.
               # Singleton methods are Exclusive to a single particular object only. Hence even the instances created from class A cannot access class methods.
               # derived class can invoke base class' singleton object. Again instances of Derived class cannot access singleton method defined on base class.
  def self.methoda_classmethod_public
    puts "hello from methoda_classmethod_public self=#{self}"
  end

  private :methoda_private
  protected :methoda_protected
end

class B < A
  def public_methodb_calling_private_methoda

      # 1) Java => private members are not inherited directly in derived class. So this will not work in Java.
                 # Derived class inherits base class' protected and public members. So if Base class' protected/public method access private member
                 # then Derived class can also 'work' on private member via inherited protected/public methods.
      # 2) Ruby => private members are inherited in Ruby. So this will work in ruby.
    methoda_private       

      # 1) Java => you cannot access private memebers directly in derived class. So this will not work in Java.
      # 2) Ruby => Will not work as private members must be accessed WITHOUT explicit receiver in derived class.
    #A.new.methoda_private  # A new object is created and we are trying to access its private member.  will not work.
    #self.methoda_private   # An equivalent in Java would be this.methoda_private(). But ofcourse in Java private members are not inherited so will not work.
      
      # 1) Java => Protected members can be accessed in derived class directly becuase they are inherited. So this will work.
      # 2) Ruby => Protected members are inherited in Ruby as well. So this will work.
    methoda_protected

      # 1) Java => protected memeber cannot be accessed in drived class using reference variable(i.e. by creating object).
      # 2) Ruby => This will work. But this will NOT work in Ruby also if below expression i.e. A.new.methoda_protected is called outside class B. 
    A.new.methoda_protected

      # 1) Java => A Java equivalent would be this.methoda_protected() . This will work in Java. As protected methods are inherited in Java directly. Needed verification.
      # 2) Ruby => This will work. Ruby will be calling inherited method. Java will also do the same.
    self.methoda_protected

      # 1) Java => Instance method can call static method (class method).
      # 2) Ruby => This will not work. Instance method CANNOT call class method.
    #methoda_classmethod_public

      # 1) Java => instance method can call static method (class method). In java it would be this.methoda_classmethod_public()
      # 2) Ruby => this will not work. Because inside instance method self will be referring to the instance of B. And instance of B CANNOT call
                 # singleton method of class A.
    #self.methoda_classmethod_public
  end

    # 1) Java => Both below statements are not allowed in Java. These are called outside any method definition.
    # 2) Ruby => Both below will work in Ruby. Hence class methods are inherited but only to be called by derived class itself.
               # class methods are singleton method. Normally singleton methods are called by only their own onjects.
               # But when in case of singleton methods defined on class (class methods), they can be called by dervied class also. (Not by derived class instances).
  methoda_classmethod_public
  self.methoda_classmethod_public
end

#A.new.methoda_private     # => will not work. (same as in Java)
#A.new.methoda_protected   # => will not work. (same as in Java). Compare and take a note of this expression inside class B as well.
#A.new.methoda_classmethod_public # => Will not work in Ruby but will work in Java. Java syntax would be: A a = new A(); a.methoda_classmethod_public() .

B.new.public_methodb_calling_private_methoda
B.methoda_classmethod_public  # => will work both in Java and Ruby

Tuesday, 1 March 2016

Understanding JAVA Nested Classes

class OuterClass {
    private String outerClassPrivateInstanceVar = "outerClassPrivateInstanceVar";
    public static String outerClassPublicStaticVar = "outerClassPublicStaticVar";
    public String outerClassPublicInstanceVar = "outerClassPublicInstanceVar";

    void outerClassInstanceMethod() {
        System.out.println("Inside outerClassInstanceMethod.");
    }

    static void outerClassStaticMethod() {
        System.out.println("Inside outerClassStaticMethod.");
    }

    // NON-STATIC Inner class
    class InnerClass {
        // Non-static innerClass cannot have static members. Following will not work.
        // static String InnerClassStaticVar = "InnerClassStaticVar";
        public void innerClassMethod() {
            System.out.println("Inside innerClassMethod.");
        }
        public void innerClassAccessOuterClassVars() {
            System.out.println(outerClassPrivateInstanceVar);
            System.out.println(outerClassPublicInstanceVar);
            System.out.println(outerClassPublicStaticVar);
        }
    }

    // STATIC Inner class
    static class InnerClassStatic {
        // Following is allowed in Static InnerClass but not in non-static inner class.
        static String StaticInnerClassStaticVar = "StaticInnerClassStaticVar";
        String InnerClassStaticInstanceVar = "InnerClassStaticInstanceVar";
        public void innerClassStaticMethod() {
            System.out.println("Inside InnerClassStatic.");
        }
        public void innerClassStaticAccessOuterClassVars() {
            // Following will not work. Beacuse InnerClassStatic is like static member inside OuterClass
            // and static members/methods can never access instance members.
            //System.out.println(outerClassPrivateInstanceVar);
            //System.out.println(outerClassPublicInstanceVar);

            System.out.println(outerClassPublicStaticVar);
        }
    }

    // Local Inner Class inside Instance method.
    void outerClassInstanceMethodForLocalClass() {
        // Local Inner Classes cannot be private, protected, public and static. Because inside method
        // these keywords have no sense. We don't use these words inside methods.
        class LocalClassInInstanceMethod {
            // Static members are not allowed in Local Inner classes defined inside instance method.
            // Following will not work.
            //static String LocalClassInInstanceMethodStaticVar = "LocalClassInInstanceMethodStaticVar";
            void localClassInInstanceMethod_instanceMethod() {
                System.out.println("Inside localClassInInstanceMethod_instanceMethod.");
            }
        }
        LocalClassInInstanceMethod localClassInInstanceMethodObj = new LocalClassInInstanceMethod();
        localClassInInstanceMethodObj.localClassInInstanceMethod_instanceMethod();
    }

    // Local Inner Class inside Static method.
    static void outerClassStaticMethodForLocalClass() {
        // Local Inner Classes cannot be private, protected, public and static. Because inside method
        // these keywords have no sense. We don't use these words inside methods.
        class LocalClassinStaticMethod {
            // Static members are not allowed in Local Inner classes defined inside static  method.
            // Following will not work.
            //static String LocalClassinStaticMethodStaticVar = "LocalClassinStaticMethodStaticVar";
            void LocalClassinStaticMethod_instanceMethod() {
                System.out.println("Inside LocalClassinStaticMethod_instanceMethod.");
            }
        }
        LocalClassinStaticMethod locallassinStaticMethodObj = new LocalClassinStaticMethod();
        locallassinStaticMethodObj.LocalClassinStaticMethod_instanceMethod();
    }

    // Anonymous Inner classes
    interface InnerInterface {
        void InnerInterfaceMethod();
    }
    // Anonymous inner class object defined at class member level.
    InnerInterface anonymousClassObj = new InnerInterface() {
        public void InnerInterfaceMethod() {
            System.out.println("Inside InnerInterfaceMethod.");
        }
    };
    void callAnonymousObjectMethod() {
        anonymousClassObj.InnerInterfaceMethod();
    }
    // Anonymous inner class inside instance method.
    //void anonymousInnerClassInsideMethod() {
    OuterClass  anonymousInnerClassInsideMethod() {
        OuterClass anon = new OuterClass() {
            void outerClassInstanceMethod() {
                System.out.println("Inside anonymousInnerClassInsideMethod.");
            }
        };
        //anon.outerClassInstanceMethod();
        return anon;
    }
}

public class InnerClassesTest {
    public static void main(String[] args) {
        OuterClass outerClassObj = new OuterClass();

        // Call to instance method using instance variable.
        outerClassObj.outerClassInstanceMethod();

        // Call to static method using instance variable. In Ruby there is something called self instead of static. And
        // self.outerClassStaticMethod  in Ruby is actually a singleton method defined on a "class object (OuterClass)" and in Ruby class
        // itself is an object. And singleton methods can be called by only object on which it is defined, in this case OuterClass object.
        // Hence in Ruby object created by a class cannot access class method. Following is invalid in Ruby.
        outerClassObj.outerClassStaticMethod();

        // NON-STATIC INNER CLASSES
        // Creating InnerClass object.
        System.out.println("====NON-STATIC INNER CLASSES====");
        OuterClass.InnerClass innerClassObj = new OuterClass().new InnerClass();
        innerClassObj.innerClassMethod();

        // Following will not work. outerClassPublicInstanceVar is not defined in InnerClass.
        //System.out.println(innerClassObj.outerClassPublicInstanceVar);

        innerClassObj.innerClassAccessOuterClassVars();

        // STATIC INNER CLASSES.
        // Creating Static Innerclass object. You will be using Class not object.
        System.out.println("====STATIC INNER CLASSES====");
        OuterClass.InnerClassStatic innerClassStaticObj = new OuterClass.InnerClassStatic();
        // You cannot use OuterClass object to use StaticInnerClass object. This is in contrast with creating InnerClass(non-static) object.
        // Also normally an object can access static class fields. But Following will not work.
        //OuterClass.InnerClassStatic innerClassStaticObj2 = outerClassObj.InnerClassStatic();

        // Access static inner class' static member using static inner class' object.
        System.out.println(innerClassStaticObj.StaticInnerClassStaticVar);
        // Access static inner class' static member using Classes directly.
        System.out.println(OuterClass.InnerClassStatic.StaticInnerClassStaticVar);
        // Access static inner class' instance member using static inner class' object.
        System.out.println(innerClassStaticObj.InnerClassStaticInstanceVar);

        // LOCAL INNER CLASSES
        System.out.println("====LOCAL INNER CLASSES====");
        outerClassObj.outerClassInstanceMethodForLocalClass();
        outerClassObj.outerClassStaticMethodForLocalClass();
        OuterClass.outerClassStaticMethodForLocalClass();

        // ANONYMOUS INNER CLASSES
        System.out.println("====ANONYMOUS INNER CLASSES====");
        outerClassObj.callAnonymousObjectMethod();
        // Following works because, interface InnerInterface is visible in this class as well due to default access.
        // If inner interface in made private then following will not work. Only inner interfaces can be made private.
        outerClassObj.anonymousClassObj.InnerInterfaceMethod();

        OuterClass anonymousObj = new OuterClass() {
            void outerClassInstanceMethod() {
            System.out.println("inside anonymousObjOfOuterClassSubClass Method.");
            }
            void anotherMethod() {
                System.out.println("Inside anotherMethod.");
            }
        };
        anonymousObj.outerClassInstanceMethod();
        // Following will not work. Because anonymousObj is refering to actually subclass of OuterClass (in memory). But it is declared as OuterClass.
        // That means, anonymousObj is actually a "Subclass of OuterClass" but its type is declared as OuterClass. Hence polymorphism will come in.
        // anonymousObj being declared as superclass variable will only be able to execute methods defined in super class not in sub class. Hence
        // following will not work.
        //anonymousObj.anotherMethod();

        //Following works provided relevant lines are un-commented inside anonymousInnerClassInsideMethod instance method.
        //outerClassObj.anonymousInnerClassInsideMethod();
        OuterClass out = outerClassObj.anonymousInnerClassInsideMethod();
        out.outerClassInstanceMethod();
    }
}
Compile and Output:
$ java -version
java version "1.8.0_66"
Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)
$
$ javac InnerClassesTest.java
$ java InnerClassesTest
Inside outerClassInstanceMethod.
Inside outerClassStaticMethod.
====NON-STATIC INNER CLASSES====
Inside innerClassMethod.
outerClassPrivateInstanceVar
outerClassPublicInstanceVar
outerClassPublicStaticVar
====STATIC INNER CLASSES====
StaticInnerClassStaticVar
StaticInnerClassStaticVar
InnerClassStaticInstanceVar
====LOCAL INNER CLASSES====
Inside localClassInInstanceMethod_instanceMethod.
Inside LocalClassinStaticMethod_instanceMethod.
Inside LocalClassinStaticMethod_instanceMethod.
====ANONYMOUS INNER CLASSES====
Inside InnerInterfaceMethod.
Inside InnerInterfaceMethod.
inside anonymousObjOfOuterClassSubClass Method.
Inside anonymousInnerClassInsideMethod.