Translate

Sunday, October 28, 2012

Object Oriented Concepts


 OO CONCEPTS

1) Data hiding
2) Abstraction
3) Encapsulation
4) Tightly Encapsulated class
5) Is – A Relation Ship
6) HAS – A Relation ship
7) method signature
8) overloading
9) overriding
10) method hiding
11) static control flow
12) instance control flow
13) constructors
14) coupling
15) cohesion
16) typecasting


Data Hiding:


The data should not go out directly i.e outside person is not allowed to access the data this is nothing but

“Data Hiding”.The main advantage of data hiding is we can achieve security.By using private modifier we can achieve this.
Ex:
Class datademo
{
private double amount;
………
}
It is highly recommended to declare data members with private modifier.

Abstraction:

Hiding implementation details is nothing but abstraction. The main advantages of abstraction are we can

achieve security as we r not highlighting internal implementation.Enhancement will become easy. With out effecting outside person we can change our internal implementation.It improves maintainability.
Note:- 
1) If we don’t know about implementation just we have to represent the specification then we should
    go for interface
2) If we don’t know about complete implementation just we have partial implementation then we
    should go for abstract.
3) If we know complete implementation and if we r ready to provide service then we should go for
    concrete class

Encapsulation:

If a class follows data hiding and abstraction such type of class is said to be ‘Encapsulated’ class.
                        Encapsulation = Data Hiding + Abstraction
Ex:
class Account
{
    private int balance;
    public void setBalance(int balance)
   {
           //validating the user & his permissions.
            this.balance = balance;
   }
   public int getBalance()
  {
      //validating the user and his permissions.
      return balance;
   }
}
The data members we have to declared as private. So that outside person is not allowed to access to directly.we have to provide Access to our data by defining setter and getter methods. i.e hiding data behind methods is the central concept of encapsulation.The main advantages of encapsulation are security, enhancement, maintainability.

Tightly Encapsulated Class
A class is said to be tightly encapsulated iff all the data members declared as private.
Ex:-
class student
{
   private String name;
   public void setName(String name)
  {
    this.name = name;
  }
  public String getName()
 {
   return name;
 }
}
Q) which of the following classes are tightly encapsulated classes?
class x
{
   private int i =10;
  private int getI();
 {
    return i;
  }
}
class y extends x
{
   public int i = 30; X
}
class z extends x
{
   private int k = 40;
}
Q)
class x
{
    int i = 0;
}
class y extends x
{
    private int j = 20;
}
class z extends y
{
    private int k = 30;
}
no class is tightly encapsulated if the parent class is not tightly encapsulated then no child class is tightly
encapsulated.
IS – A RelationShip
 Also known as ‘inheritance’.
 By using extends keyword we can implement inheritance.
 The main advantage is reusability.

Note:- parent class reference can be used to hold child class object but by using that reference we r not
allowed to call child class specific methods.

class test
{
   public static void main(String arg[])
  {
     p p1 = new p();
     p1.m1();
     p1.m2();
     p1.m3(); C.E: Child class methods are not available to the parent class.
     c c1 = new c();
     c1.m1();
    c1.m2();
    c2.m3();
    p p2 = new c();
    p2.m1();
    p2.m2();
    p2.m3();  C.E: By using parent class reference we can’t call child class specific method
    c c4 = new p() C.E: Child class reference can’t be used to hold parent class object.
  }
}
A class can extend only one class at a time but an interface can extend any no of interfaces
simultaneously.

HAS – A RelationShip

 Also known as Composition or Aggregation .
 There is no specific keyword, but most of the cases we can implemented by using new keyword.
 Main advantage is reusability.
Ex:
class engine
{
   m1(){}
   m2(){}
  .
  .
  .
 }
class car
{
   engine e = new engine();
    .
    .
}
Class car has engine.
HAS – A relationship increases dependency b/w components and creates maintainability problems.

Method Signature:

In java method signature consists of method name and arguments list( including order also) Compiler uses method signature to resolve method calls. Two methods with the same signature are not allowed in any java class, violation leads to compile time error.

Ex:
class Test
{
    public void m1(int i)
  {
   }
   public void m2()
  {
  }
  public int m1(int i)
  {
  }
 public void m1(int i, float f)
 {
 }
 method signature
}
C.E:-m1(int) is already defined in Test . In java return type is not part of method signature.

OverLoading:


Two methods r said to be overloaded iff the method names are same, But arguments are different(Atleast Order) Lack of overloading increases complexity of the program in the case of ‘c’ language. For the same requirement we should maintain different method names if arguments are same. In C
                 abs(int i)  only for int arguments.
                 fabs(float f)  only for float arguments.
                labs(long l)  only for long arguments.
But in java two methods with the same name is allowed eventhough arguments r different.
                abs(int i)
                abs(float f)
                abs(long l)
Ex:-
Case1:
class Test
{
   public void m1()
  {
    System.out.println("no-args");
  }
  public void m1(int i)
 {
    System.out.println("int-args");
 }
  public void m2(double d)
 {
    System.out.println("double-args");
 }
 public static void main(String[] args)
{
   Test t = new Test();
   t.m1();
   t.m1(10);
   t.m1(10.5);
 }
}
The overloading method resolution is the responsibility of compiler based on reference type and method

arguments. Hence overloading is considered as compile-time polymorphism or EarlyBinding. Automatic promotion in overloading
Ex:-
Case2:
class Test
{
  public void m1()
 {
   System.out.println("no-args");
 }
 public void m1(int i)
{
   System.out.println("int-args");
 }
 public void m1(float f)
 {
    System.out.println("float-args");
 }
public static void main(String[] args)
{
   Test t = new Test();
   t.m1();
   t.m1(10);
   t.m1(10l);
   t.m1(10f);
   t.m1('a');
   t.m1(10.5);
}
}
In the case of overloading if there is no method with the required argument then the compiler won’t raise

immediately compile time error. First it will promote arguments to next level and checks is there any

matched method with promoted arguments, if there is no such method compiler will promote the argument
to the next level and checks for the matched method. After all possible promotions still the compiler unable
to find the matched method then it raises compile time error.
The following is the list of all possible Automatic promotion.
Ex:-
class Test
{
   public void m1(String s)
  {
     System.out.println("String Version");
   }
   public void m1(Object o)
  {
     System.out.println("Object Version");
  }
  public static void main(String arg[])
  {
     Test t = new Test();
     t.m1("raju"); String Version
     t.m1(new Object()); Object Version
     t.m1(null);
   }
}

Ex:-
Case3:
class Test
{
   public void m1(String s)
   {
      System.out.println("String Version");
   }
   public void m1(StringBuffer sb)
  {
      System.out.println("StringVersion");
   }
  public static void main(String arg[])
  {
     Test t = new Test();
     t.m1("raju");
     t.m1(null);
   }
}
So it produces Ambiguity error.
Note:- we can define a single method which can be applicable for any type of primitive argument, as
follows m1(double d) By automatic promotion instead of double we can give char, byte, short, int, long, float, double. Based on the same approach square root method in math class is declared. public static double sqrt(double d) If we want to declare a method which can be applicable for byte, short, char, int, long we should declare as follows.m1(long)
Ex:-
class Test
{
    public void m1(int... i)
    {
            System.out.println("var-arg");
      }
    public void m1(int i)
   {
             System.out.println("int-arg");
    }
    public static void main(String arg[])
   {
        Test t = new Test();
         t.m1(); //var-arg
         t.m1(10,20); //var-arg
         t.m1(10); //int-arg
   }
}
var-arg method will always get least priority i.e if no other method matched then only var-arg method will
get chance for execution.
Ex:-
class Test
{
    public void m1(int i, float f)
   {
        System.out.println("int, float");
   }
   public void m1(float f, int i)
  {
     System.out.println("float, int");
  }
  public static void main(String arg[])
 {
        Test t = new Test();
        t.m1(10.5f, 10);
        t.m1(10, 10.5f);
        t.m1(10, 10); // C.E : reference to m1() is ambiguous
        t.m1(10.5f, 10.5f);// C.E : can’t find symbol method m1(float,float)
   }
}
Ex:
class Animal
{
}
class Monkey extends Animal
{
}
class Test
{
   public void m1(Animal a)
   {
        System.out.println("Animal Version");
   }
 public void m1(Monkey m)
{
   System.out.println("Monkey Version");
}
public static void main(String arg[])
{
    Test t = new Test();
    Case1: Animal a = new Animal();
                t.m1(a); //Animal Version
    Case2: Monkey m = new Monkey();
                t.m1(m); //Monkey Version
   Case3: Animal a1 = new Monkey();
              t.m1(a1); //Animal Version
 }
}
Overloading method resolution will always take care by compiler based on the reference type but not based
on runtime object.

Overriding:

What ever the parent has by default available to the child class through inheritance, If the child class is not
satisfied with the parent class implementation then the child is allowed to overwrite that parent class method
to provide it’s own specific implementation, this concept is nothing but “overriding”.
Ex:
class P
{
   public void property()
   {
       System.out.println("Land, gold, cash");
   }
   public void mary()
  {
        System.out.println("Subbalakshmi");
   }
}
class C extends P
{
       public void mary()
      {
          System.out.println("Priyanka");
       }
}
class Test
{
      public static void main(String[] args)
     {
        P p1 = new P();
        Case1: p1.mary(); //Subbalakshmi
                   C c1 = new C();
        Case2: c1.mary(); //Priyanka
                   P p2 = new C();
         Case3: p2.mary(); //Priyanka
     }
}
Overriding method resolution will take care by JVM based on runtime Object. Hence overriding is
considered as runtime polymorphism or dynamic polymorphism or latebinding.

The process of overriding method resolution is also known as “dynamic method dispatch”.

Rules for overriding

       1) The method names and arguments(including order) must be same. i.e signatures of the methods
            must be same.
       2) In overriding the return types must be same but this rule is applicable only until 1.4 version but
             from 1.5 version onwards co-variant return types also allowed. i.e the child class method return type
             need not to be same as parent class method return type it’s child class also allowed.
Ex:
Parent : Object(covariant returntype).
Child : String, StringBuffer, Object…..
Parent : String
Child : Object X

Because String to Object is not a covariant.

Parent : double
Child : int X

Because co-variant return types are not applicable for primitive types.
Which of the following are valid overriding methods……?

Parent : public void m1()
Child : public void m1()
Parent : public int m1()
Child : public long m1() X
Parent : public Object m1()
Child : public String m1()
Parent : public String m1()
Child : public Object m1() X

          3) final method can’t be overridden in child classes. Private methods are not visible in the child
classes. Hence they won’t participate in overriding. Based on our requirement we can take exactly
same declaration in child class, But It is not overriding.
Ex:
class P
{
   private void m1()
  {
   }
}
class C extends P
{
   private void m1()
  {
   }
}
Here it is not overriding child class specific method.

      4) native methods can be overridden as non-native, similarly we can override abstract methods,
          synchronized methods.We can override a non-abstract method as abstract also
     The following are possible types
     5) while overriding we are not allowed o decrease access privileges. Otherwise compile time error
         but we can increase access privileges. The following is the list of valid with respect to access privileges.
     6) while overriding the size of checked exceptions we are not allowed to increase in throws class but we                                                               can decrease the size of checked exceptions. But there are no restrictions on unchecked exceptions.

Overriding in static methods
A static method can’t be overridden as non-static
Ex:
class P
{
   public static void m1()
  {
   }
}
class C extends P
{
   public void m1()
  {
  }
}
O/P:-
class P
{
  public void m1()
 {
  }
}
abstract class C extends P
{
   public abstract void m1();
}
abstract class P
{
    public abstract void m1();
 }
class C extends P
{
   public void m1()
  {
   }
}

Similarly a non-static method can’t be overridden as static method. If both parent and child class methods are static then there is no compile time error or run time error it seems that overriding is happened but it is not overriding this concept is called “method hiding”.


All the rules of method hiding are exactly similar to overriding, except both methods declared as static.

In the case of method hiding method resolution will take care by compiler based on reference
type(But not runtime object).
Ex:
class P
{
  public static void m1()
 {
     System.out.println("parent method");
  }
}
class C extends P
{
    public static void m1()
   {
        System.out.println("child method");
    }
}
class Test
{
    public static void main(String arg[])
    {
          P p = new P();
          Case1: p.m1(); //parent method
                     C c = new C();
         Case2: c.m1(); //child method
                    P p1 = new P();
         Case3: p1.m1(); //parent method
     }
}
In the case of method hiding the method resolution will take care by compiler based on reference type. Hence method hiding is considered as ‘static polymorphism’ or ‘compile timepolymorphism’ or early binding’.

Overriding in the case of Variable

Overriding concept is not applicable for variables. And it is applicable only for methods. variable resolution always takes care by compiler based on reference type.

Ex:
class P
{
   int i = 888;
    static
    non-static
 }
class C extends P
{
   int i = 999;
}
class Test
{
   public static void main(String arg[])
  {
      P p = new P();
     Case1: System.out.println(p.i); //888
                C c = new C();
     Case2: System.out.println(c.i); //999
                P p1 = new C();
     Case3: System.out.println(p1.i); //888
  }
}
Comparison between Overloading and Overriding
         Property                                             Overloading                                         Overriding
    1) Method names                                         Same                                                   Same
    2) Arguments Different              (at least order)Same                                                  Same(including order)
    3) signature                                              Different                                                   Same
    4) return type                           No rule or no restriction                                   Must be same until 1.4
                                                                                                                     version. But from 1.5 version
                                                                                                onwards co-variant return types are allowed
     5) throws clause                     No restrictions                       The size of the checked exception should                   
                                                                                                not be increased. But no restrictions for       
                                                                                                unchecked exceptions.
    6) Access Modifier                  No restrictions                      Should be decreased
    7) Private/final/static               Can’t be overloaded                 Can’t be overridden
    8) Method resolution     Method resolution takes care by     Takes care by JVM based on runtime object
                                         compiler based on reference type
                                         and arguments

     9) Other names              Compile time (or) static                    Runtime (or) dynamic  
                                         polymorphism (or) early binding         polymorphism (or) late binding

Consider the following parent class method declaration….!
Parent : public void m1(int i)
Which of the following methods are allowed in the child class.
Child : 1) private void m1(float f)throws Exception (overloading)
2) public void m1(int i)throws classCastException (overloading)
3) public final void m1(int i) (overloading)
4) private abstract void m1(long l)throws Exception X (private & abstract)
5) public synchronized int m1() throws IOException (over loading)
6) public int m1(int i) X
7) public void m1(int i)throws Exception X (Exception Increased)


static Blocks:


If we want to perform some activity at the time of class loading, Then we should define that activity at static blocks because these(static blocks) will execute at the time of class loading only. We have to load native libraries at the time of class loading. Hence we have to define this activity inside the “static block”.


Ex:
class Native
{
  static
  {
    System.loadLibrary("native Library path");
  }
}

After loading database driver compulsory we should register with the driver manager. But it is not  required to perform explicitly this registration because in every driver class there should be one static block to perform this registration. Hence at the time of loading the database driver automatically registration will be performed.

Ex:
class DatabaseDriver
{
  static
  {
      //Register Driver with Driver Manager
   }
}
Case1:- with out using main method we can able to print some statement to the console.
Ex:
class StaticDemo
{
   static
  {
           System.out.println("Hello....I can print ");
           System.exit(0);
   }
}
With out using main method, static block still we are able to print some statement on the console.
Ex:
class StaticDemo
{
    static int i = m1();
    public static int m1()
   {
      System.out.println("Hello ....I am able to print");
      System.exit(0);
      return 1;
   }
}


Constructor:


After Creation of Object compulsory we should perform initialization then only that object in a position to provide service to others.At the time of Object Creation some peace of code will execute automatically to perform initialization that peace of code is nothing but “Constructor”.Hence the main Objective of constructor is to perform initialization.If we don’t have constructor we will face burden. For example see the following code.
Ex:
class Student
{
    String name;
    int rollno;
    public static void main(String[] args)
   {
         Student s1 = new Student();
         Student s2 = new Student();
         Student s3 = new Student();
         Student s4 = new Student();
         s1.name = "Malli";s1.rollno = 101;
         s2.name = "Sankar";s2.rollno = 102;
        s3.name = "Kiran";s3.rollno = 103;
        s4.name = "Sai";s4.rollno = 104;
       System.out.println(s1.name+"-----"+s1.rollno);
       System.out.println(s2.name+"-----"+s2.rollno);
       System.out.println(s3.name+"-----"+s3.rollno);
        System.out.println(s4.name+"-----"+s4.rollno);
   }
}
To over come this type of burden constructor was introduced.
Ex:-
class Student
{
   String name;
    int rollno;
   Student(String name, int rollno)
  {
     this.name = name;
     this.rollno = rollno;
  }
  public static void main(String[] args)
 {
     Student s1 = new Student("raju",101);
     Student s2 = new Student("mani",102);
     System.out.println(s1.name+"-----"+s1.rollno);
     System.out.println(s2.name+"-----"+s2.rollno);
 }
}

Rules for Constructor:- While writing constructors we should follow the following rules.

1) The name of the constructor and name of the class must be same.
2) The only allowed modifiers for the constructors are public, private, protected, . If we are using any other modifier we will get C.E(Compiler Error).
Ex:
class Test
{
   static Test()
   {
      ----
   }
}
C.E:- modifier static not allowed here.
3) return type is not allowed for the constructors even void also. If we r declaring return type then the
compiler treats it as a method and hence there is no C.E and R.E(RuntimeError).
class Test
{
   void Test()
   {
       System.out.println("Hai .....");
    }
   public static void main(String arg[])
  {
     Test t = new Test();
   }
}
It is legal(But Stupid) to have a method whose name is exactly same as class name.Here it was treated as method.
Default Constructor

If we r not writing any constructor then the compiler always generate default constructor.If we r writing at least one constructor then the compiler won’t generate any constructor.Hence every class contains either programmer written constructor or compiler generated default constructor but not both simultaneously.
Prototype of default constructor:

1) It is always no-arg constructor.
2) It contains only one – line super(); This is a call to superclass – constructor it is no-argument call only.
3) The modifier of the default constructor is same as class modifier(either public or default).

Programmers Code Compiler Generated Code
class Test
{
}
class Test
{
 Test()
 {
    super();
  }
}
public class Test
{
}
public class Test
{
   public Test()
  {
    super();
   }
 }
class Test
{
private Test()
{
}
}
class Test
{
  private Test()
  {
     super();
  }
}
class Test
{
   void Test()
  {
  }
}
class Test
{
    void Test()
   {
   }
  Test()
  {
     super();
  }
}
class Test
{
   Test()
   {
      this(10);
   }
  Test(int i)
  {
   }
}
class Test
{
   Test()
  {
    this(10);
  }
  Test(int i)
  {
     super();
  }
}
The first line inside any constructor must be a call to super class constructor(super()) or a call to
overloaded constructor of the same class(this()). If we are not taking any thing then the compiler will
always place super()

super() & this() in constructor

we should use as first statement in constructor. We can use either super or this but not both simultaneously. Outside constructs we can’t use i.e we can invoke a constructor directly from another constructor only.

Overloaded Constructor

A class can contain more than one constructors with different arguments. This type of constructors  are called “overloaded constructor”.

Ex:-
class Test
{
  Test()
  {
    this(10);
    System.out.println("No-arg constructor");
  }
 Test(int i)
 {
   this(10.5);
   System.out.println("int-arg");
  }
Test(double d)
{
   System.out.println("double-arg")
}
public static void main(String arg[])
{
    Test t1 = new Test();
    Test t2 = new Test(10);
    Case1:
    class Test
   {
      Test()
     {
         super()
         System.out.println("constructor")
     }
}
Case2:
class Test
{
  Test()
  {
      System.out.println("constructor")
      super();
   }
}
C.E: Call to super() must be first statement in constructor
Case3:
class Test
{
   Test()
   {
      super();
      this(10);
      super("Constructor");
   }
   Test(int i)
   {
      System.out.println("Constructor")
   }
}
Case4
class Test
{
    public void m1()
   {
      super();
    }
}
C.E: Call to to this must be first statement in
C.E: Call to to Super must be first statement in
  Test t3 = new Test(20.5);
   Test t4 = new Test('a');
   Test t5 = new Test(10l);
 }
}
Inheritance concept is not applicable for constructor and hence overriding is also not applicable.Recursive Method invocation is runtime exception saying stack over flow error.Because super calls no-argument constructor in parent.when ever we r writing any constructor. It is remanded to provide no-arument constructor also. If the parent class contains some constructors then while writing child class constructor we should take a bit care.

If the parent class constructor throws some checked exception. Compulsory the child class constructor should throw the same checked exception or it’s parent other wise compile time error.
class Test
{
   public static void m1()
   {
      System.out.println("m1 method");
     m2();
   }
   public static void m2()
  {
     System.out.println("m2 method");
     m1();
   }
  public static void main(String arg[])
  {
     m1();
    System.out.println("Hello......hai");
  }
}
class Test
{
   Test()
   {
     this(10);
   }
   Test(int i)
   {
     this();
    }
    public static void main(String arg[])
    {
        System.out.println("Hai........hello");
    }
}
No Compilar Error and No Runtime Error C.E: Recursive constructor invokation
class p
{
}
class c extends p
{
}
class p
{
p()
{
}
}
class c extends p
{
}
class p
{
p(int i)
{
}
}
class c extends p
{
}
C.E:
If the parent class constructor throws unchecked exception then child class constructor not required
to throw that exception
Ex:
class p
{
p() throws ArithmeticException
{
}
}
class c extends p
{
c()
{
super();
}
}


Coupling
It is also one of the feature of OOPs. The degree of dependency between the components is called coupling.
Ex:
These components are tightly coupled with each other. With out effecting any component we can’t modify
any component. This type of programming is not recomanded.
When ever we are developing the components compulsory we should maintain very less dependency
between the components i.e we have to maintain loosely coupling.
The main advantages of loosely coupling are:
1) It imporves maintainability.
2) It makes enhancements easy.
3) It produces reusability.
Cohesion
For every component we have to define a well defined single purpose. Such type of components are said to
be followed high “cohesion”.
Ex:-
If we define a single servlet for all required functionalities of mail application like displaying
login page, Validating the user, Displaying Inbox page etc…
Then for every small change entire component will be disturbed and it reduces maintainability and
suppresses reusability of code.
To resolve this problem. For every task we can define a separate component like login.jsp for displaying
login page, validate servlet for validation purpose, inbox servlet, For displaying mails etc….
By using this approach we can perform the modification in any component with out effecting the remaining.
And it imporves maintainability. It also promotes reusability. When ever validation required the same
validate servlet we can use.
The main advantages of High Cohesion are:
1) It imporves maintainability.
class A
{
static int i = B.m2();
.
.
.
.
}
class B
{
static int m2()
{
return c.j;
}
}
class C
{
static int j = D.l;
.
.
.
.
}
class D
{
static int l = 30;
.
.
.
.
}
2) Enhancements is easy.
3) Promotes reusability.


typeCasting:General syntax of typecasting For type casting we have to check at 3 regains those are

Compile time checking 1:There should be some relation ship between the type of ‘d’ and ‘c’. other wise we will get compile time error saying inconvertable types
found : d
required : c
Ex:
String s = “raju”;
Object o = (Object)s;
Because Object is parent to String
String s = “raju”;.
Object o =(StringBuffer)s;
Compile time checking 2
‘c’ must be same or derived type of ‘A’ other wise compile time error. Saying incompatable types
found : c
required : A
Ex:
String s = “raju”;
Object o = (String)s;
Because String is child of Object.
String s = “raju”;
StringBuffer sb = (Object)s;
Runtime Checking
The internal object type of ‘d’ must be same or derived type of ‘c’ other wise we will get
RuntimeException saying
ClassCastException : ‘d’ type
Ex:
A b = (c) d;
class/Interface
reference variable class/interface
reference variable/Object
Object o = new String(“raju”) ;
StringBuffer sb = (StringBuffer)o;
Object o = new String(“raju”);
String s = (String)o;
Because internal Object type of o is String , so ‘c’(String), ‘d’(String) are same.
Consider the following Figure
Base ob1 = new Derived2();
Object ob2 = (Base)ob1;
Derived2 ob3 = (Derived2)ob2;
Base ob4 = (Derived2)ob3;
Derived2 ob5 = (Derived1)ob4; //R.E ClassCastException
Conseder the following Code
class Dog
{
}
class Beagle extends Dog
{
}
class Test
{
public static void main(String arg[])
{
Beagle b1 = new Beagle();
Dog d1 = new Dog();
Dog d2 = b1;
//insertcode
}
}
Which of the following are allowed to the line 9(//insertcode)?
1) Beagle b2 = (Beagle)d1;
2) Beagle b3 = (Beagle)d2;
3) Beagle b4 = d2;
4) Non of the above
Ans: in 1 Runtime checking failed(3rd case) and in 3 Comiple time error Incompatable types(2nd
Case)
Conseder the following Code
Object
Base
Derived1 Derived2
class X
{
void do1()
{
}
}
class Y extends X
{
void do2()
{
}
}
class Test
{
public static void main(String arg[])
{
X x1 = new X();
X x2 = new Y();
Y y1 = new Y();
//insertcode here to compile fine
}
}
Which of the following are allowed to compile fine
A) x2.do2();
B) ((Y)x2).do2();
C) ((Y)x2).do1();
D) ((Y)x1).do1(); //C.E

No comments: