I can't get a clear idea about inheritance in Java. For instance, I have:
class A
{
...
public void MethodA();
}
Here is everything is clear. Then I want a (sub)class:
class B extends A
{
...
public void MethodB();
}
Then I create an instance of A. Then I want to get an instance of B having all the stuff from A. I want to make something like aA = new B(); but get an error.
Using this thing is not really comfortable:
A aA = new A(...);
B aB = new B(null,null,...);
aB = aA
How should I make it correctly and get a clear idea about inheritance in Java?
UPD: So how can i get an instance of B having all the stuff of A?
It sounds like you want an instance of B in the first place. Once you have such an instance, you can use it whenever either A or B is required.
Put another way, every instance of B is automatically also an instance of A.
This is called the Liskov Substitution Principle.
In your example, A - superclass, B - subclass.
A subclass possesses all the attributes and operations of its superclass (because a subclass inherited all attributes and operations from its superclass). This means that a subclass object can do whatever its superclass can do. As a result, we can substitute a subclass instance when a superclass instance is expected, and everything shall work fine. This is called substitutability.
You need to understand the IS-A relationship. Let's discuss an example of Employee and Manager relationship.
class Employee{
public Employee(){
System.out.println("Employee obj");
}
}
class Manager extends Employee{
public Manager(){
System.out.println("Manager obj");
}
}
By extending Employee we are declaring Manager as a specialization of Employee. Therefore, every Manager is an Employee but every Employee is not Manager.
A reference of type Employee can refer to the objects who satisfy the IS-A relationship. Therefore, these are perfectly legal to write:
Employee emp1 = new Employee();
Employee emp2 = new Manager();
However, if we try to write
Manager man1 = new Employee(); //Wrong: Compilation error.
This violates the IS-A relationship. As a result of this we get compile time error. In order to avoid this kind of compilation error we need to add a cast to type Manager. But, casting to type Manager only avoids compilation issues. You will get a java.lang.ClassCastException as a result of of this kind of casting.
Manager man1 = (Manager) new Employee(); //Wrong: avoids compilation error but will generate a ClassCastException at runtime.
I suggest you to go through the Java Language Specification: Section 5.5.1 to get a full idea of casting a reference type.
Every instance of B has all of stuff from A, because it is an A. But it seems like you actually want to create an instance of B from a given instance of A. This isn't possible, unless you specifically write your class so as to allow it:
public class B extends A {
public B(A original) { ... }
}
and later
A a = new A();
B b = new B(a);
Related
If I have super class (Animal) and a sub class (Cat).
What does the third point mean? And when we have to cast?
Cat obj = new Cat(); means creating an object from Cat class
Animal obj = new Animal(); means creating an object from Animal class
Animal obj = new Cat();
First lets understand Class, reference and Object. Suppose we have a class named SomeClass
SomeClass ref = new SomeClass();
Above we have an Object of SomeClass created in Heap and a reference variable refers to it. We have named the reference variable as ref. Object is present in heap and we can just access it using a reference. So Object type is of the actual class (on which new keyword has been applied). Reference variable type can be of actual class or its Parent class.
Now let us see the relationship of Inheritance. A class inheriting from another class share a Child-Parent relationship.
Child inherits the behaviour of its Parent and can then override some of the behaviour and also can add some additional behaviour. Hence Object of Child can be used at any place where Parent object is expected, as Child has all the behaviour of its Parent so invoking any behaviour present in the Parent will be handled by the Child.
Parent class do not know about the additional behaviour of its child class ( child class is written later in time.) Hence object of Parent can not be used at the places where Object of Child is expected (If additional behaviour of Child is invoked on Parent object then it will not be honoured).
Now let us assume we have classes ParentClass and ChildClass such that ChildClass inherits ParentClass
ParentClass reference = new ParentClass(); // Valid
ParentClass reference = new ChildClass(); //Valid
ChildClass reference = new ChildClass(); //Valid
ChildClass reference = new ParentClass();// Not Valid.
Note that
ParentClass reference = new ChildClass(); // Here Object is of type ChildClass and Reference is of type ParentClass.
Now when to cast. Any place expecting the object of ParentClass, there is no need to cast, both the objects (of ParentClass or of ChildClass) are fine.
Any place expecting the Object of type ChildClass but if we have a case like below then casting is needed.
public void someMethod(ChildClass expected){
//some implementation
}
ParentClass ref = new ChildClass();
someMethod(ref);//Invalid : Compilation Issue
someMethod((ChildClass)ref);// Valid
ParentClass anotherRef = new ParentClass();
someMethod(anotherRef); // Invalid : Compilation Issue
someMethod((ChildClass)ref); //Invalid, compiles but Runtime it will fail.
Thumb rule : Child is Child, Child is Parent, Parent is Parent , Parent is not Child.
Another example for understanding.
public abstract class List{
public abstract void add(int element);
public abstract void remove(int element);
public int size();
}
public class Application{
private List listReference;
public void setList(List ref){
listReference = ref;
}
}
//Now you may create sub classes as below
public class ArrayList extends List{
// all the abstract methods of List have been implemented
}
public class LinkedList extends List{
//all the abstract methods of List have been implemented
}
Now in main method you can pass ArrayList or LinkedList or any other implementation.
public class Init{
public static void main(String[] args){
Application app = new Application ();
app.setList(new LinkedList());
//or you can set it like this
List listRef = bew ArrayList();
app.setList(listRef);
//or you can set it like this
LinkedList linkedListRef = new LinkedLiet();
app.setList(linkedListRef);
}
}
Notice that the method setList() accepts List type of reference and we can provide any implementation of the List abstraction. This leads to a flexible design.
Classes should be dependent on the abstraction. Programming to interface is a Design Principle which leads to easy maintenance of the application code.
The reason why this is confusing on the face of it is that it is not something that you would typically do in real code, except in the case of a Factory.
As hinted at in Zabuza's comment, you can do this because a Cat 'is-a' kind of Animal and so you can assign an object of type Cat to an object of type Animal. But you can't do the assignment the other way of course, because an Animal is not a kind of Cat.
Now, there are some lurking issues that come with actually being able to create an instance of the the supertype as well as the subtype that mean you typically wouldn't actually do this in real code because it complicates a lot of things down the road. What you would more likely do is make Animal an interface and have a GenericAnimal class that implements it, along with having Cat implement it.
Say you have an object that represents a zoo, and most zoos typically have a collection of animals. The most obvious way to represent this would be this:
java.util.Collection<com.myproject.Animal> zooAnimals;
So now imagine the zoo builds a new habitat, and it's for a lion. For the sake of the story assume we have a very lazy data model and instead of having a specific com.myproject.animals.cats.Lion subtype we just said "lions are cats, close enough". So to update the data structure that tracks all the animals and their names and addresses and favorite foods and whatever else, we might do this:
com.myproject.Animal newArrival = new com.myproject.animals.Cat("Larry the Lion", "Africa Exhibit", "Gazelles");
zooAnimals.add(newArrival);
Now imagine that the zoo continues to grow, and gets an Ostrich in the Africa habitat. And the same lazy data model applies so we just call it a Bird.
com.myproject.Animal newArrival = new com.myproject.animals.Bird("Oliver the Ostrich", "Africa Exhibit", "Whatever Ostriches Eat");
zooAnimals.add(newArrival);
Now actually writing that exact code would normally only happen in very specific cases inside a factory object or something, and realistically type hierarchies like this have a tendency to not work very well in practice at all, contrary to what a lot of us learned in Object Oriented Programming class, but for the sake of the question that is an example situation where you might do what you are asking about.
Lastly, you also asked when you have to cast. You would have to do this if you had code that needed to know about any special methods or fields that the Cat or Bird types have that Animal does not have. For instance the Cat type might have a property called tailLength because cats typically have tails and for whatever reason the zoo likes to keep track of that. Similarly the Bird type might have a property called wingSpan because birds have wings and we want to keep track of how big they are. The Animal type doesn't have any of these properties so if we get the object for the lion or the ostrich out of the zooAnimals collection (and maybe we looked at the name or something to figure out it was the lion) we would have to cast back to the Cat type in order to access the tailLength property. Same thing for the ostrich and it's wingspan.
for( Animal theAnimal : zooAnimals ){
if( theAnimal.getName().equals("Larry the Lion") ){
Cat theCat = (Cat)theAnimal;
System.out.println("Larry's tail is " + theCat.getTailLength() + " inches long";
}
else if( theAnimal.getName().equals("Oliver the Ostrich") ){
Bird theBird = (Bird)theAnimal;
System.out.println("Oliver's wingspan is " + theBird.getWingSpan() + " inches";
}
}
Again you probably wouldn't actually do something like that in real code, but perhaps it helps to illustrate the example.
Let's say I have the following interface and classes defined:
public interface I { void a(); }
public class A implements I {
public void a() { System.out.println("A"); }
}
public class B implements I {
public void a() { System.out.println("B"); }
public void b() { System.out.println("C"); }
}
And then I run the following code:
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
I i;
i = a;
i.a(); // prints "A"
i = b;
i.a(); // prints "B"
i.b(); // 1st problem: i can't seem to find method b. Why?
b = i; // 2nd problem: b can't be assigned to i although i references an object of class B?
b = (B)i; // why does this work fine...
a = (A)i; // 3rd problem: ...but this here doesn't?
}
}
So here are my questions:
First Problem
Why can't i.b() be called?
i points to the same object as b, an object of class B which does have a method b.
So why does i.a() call the right method (the one that prints out "B") but i.b() doesn't resolve at all?
Does the fact that i was declared as being of type I (an interface) have anything to do with that? Does this mean that in an assignment X x = new Y() where Y extends X, one can only ever call methods on x that are already declared in X, and not just specific to Y?
Second Problem
Why can't b be assigned to i although i references an object of class B? b and i already reference the same object, don't they? So why does it cause an error if I try to assign b to i - the end result of which should be identical to the state of the program before that assignment, unless I'm missing something significant.
Third Problem
Why can I cast i to type B now although I couldn't assign b to i earlier, and why doesn't casting i to A work?
I'm assuming my confusion is somehow rooted in an unclear distinction between the reference variables and the objects they're referencing, as well as the differences between the types of these variables and objects. I just can't quite explain these occurrences - and in particular the first problem confuses me a lot.
For the first problem:
You can use the interface reference to call only the methods it declares
For the second problem:
You can use interface reference to invoke methods in the classes that implement the interface. However, there is no use to assign interface reference to a class reference since interface reference doesn't have any methods that can be invoked.
for the third problem:
You have assigned previously
i=b
and hence
b=(B)i
works fine.
However,
a=(A)i
wouldn't work because i stores b and not a
First of all, learn Java (and/or OO (object oriented)) programming...
Variable i is a reference to an object instance that implements interface I. Method b() was not declared in interface I, thus it is not visible through i.b().
To be able to call it, i needs to be casted, EG: ((B) i).b()
Variable b is a reference to an object that is an instance of class B, and cannot be assigned to any reference that itself is not declared as an instance of B.
Again, a cast needed, EG: b = (B) i
Class B is not a child of class A. They both implement interface I, but A is not parent of B.
It's not a problem at all but It's behavior of inheritance and polymorphism.
Please note that when you
I i = new A();
Left hand side (I) will tells compiler which all methods it can call using that reference.
Right hand side (A) will tells the runtime which method should execute using that method call
So in your case
1 Problem
you can not call b() since b() is not there in inteface I
2 Problem
you are casting interface to object b and then calling b() so its working fine.
Let's say we have class A as a parent class, and class C that extends it.
class A
{
void m()
{
System.out.println("A.m");
}
}
class C extends A
{
#Override
void m()
{
System.out.println("C.m");
}
}
What's the difference between reference A a and C c when we use them to point to the same object type, for example A a = new C(); and C c = new C();?
From this question: Java inheritance vs. C# inheritance, it looks like that as a and c points to object type of C, and there seems no difference in using them.
I tested this code, and they all prints C.m.
class inherit {
void x(A a)
{
a.m();
}
public static void main(String[] args) {
System.out.println("hello");
A a = new C();
C c = new C();
a.m();
c.m();
new inherit().x(a);
new inherit().x(c);
}
}
That depends what the object is going to be used for.
If what you actually need is an object that has A's interface(i.e. A's type), it's strongly recommended to use A a = new C();. This way it makes it clear that you want an A interface, not a C implementation. Later when you change your mind, you can safely change it to A a = new Another_Subtype_Of_A(); without breaking other code.
This is especially true when A is an interface(In your case, A is a class). For example, if you just want a list, List list = new ArrayList(); is clearly better than ArrayList list = new ArrayList();. That's called "programming to interface, not implementation".
If you're creating an object that specifically needs C's interfaces(esp. those not present in A), you'd better choose C c = new C();. If you write A a = new C() instead, sooner or later you still have to cast the object to C(because A doesn't have all of your desired interfaces), so why bother?
It's not about the runtime type of the variable. You may only know you have a Vehicle object at compile time and based on user input, that may be a GarbageTruck or SportsCar.
GarbageTruck t;
...
t = new SportsCar(); //can't do this!
// so we do this:
Vehicle t;
if(user.isFast()) {
t = new SportsCar();
} else {
t = new GarbageTruck();
}
Java is all about Interfaces and Implementations.
An Interface is simply a set of public fields (methods & properties) the describe how users can interact with a class that implements the interface.
An Implementation is the code that actually makes those methods and properties do something. An Implementation can be a class that implements an interface, or it could be a subclass of some other implementation.
When you instantiate a class, you're writing code like:
Interface a = new Implementation();
Often times, we wrap the Interface and the Implementation all together... put another way, when we define a class, whether we're explicitly implementing an interface or not, we're defining an Interface with every public method we write.
Thus, it's the Interface that affects what methods we can call, but it's the Implementation that affects what happens when we call them.
firstly A is parent class and C is child class when you do A a = new A() then object of A is created and hold by A handle. When you do C c = new C() then object ofC is creating and C handle holds it.. But when you do A a = new C() then object ofC is created and Ahandle holds it. It means all the properties ofC is now been used. Although handle ofA is used by properties (instance) of C are used. This us polymorphism. Now it will used all the overloaded methods of C and not of A
Usages as an example
The difference come when you create a large project having methods created for child classes
Assume you have hello method
public void hello(C c) { }
In future you have another class B which extends A.. in that case you cannot use hello as its argument is of type C.. And imagine you have many classes as a child of A which need to use such method (then how many such methods you will create). Polymorphism is the rescue
You create hello with A as argument
public void hello (A x) { }
and now you can use same method for all the children of A..
A c = new C()
A b = new B()
Now all can use hello
this is the beauty of polymorphism
I want to know about the advantage in between the creating an object for sub class but assigning class A ref instead of assigning Class B ref. which is shown in line1,line2 below code
class A
{
int b=10;
}
class B extends A
{
int b=12;
}
class Test
{
public static void main(String[] args)
{
A a=new B(); //line1
//B a=new B();//line2
System.our.println(a.b);
}
}
If you're not going to need any methods specific to B, in other words, you're strictly going to use it as an A, it's an advantage for readability to state so.
But the main advantage comes to light when you use the general type in a method declaration:
public String resolveName(A a) { ... }
If you used B here for no good reason, then you would unnecessarily cripple your method. It could have worked for any A, but it works only for B.
try reading this: Polymorphism
In your short example there's no real advantage,.
But in general your question is about what polymorphism is good for?
And the answer goes back to the need of OOP methodology.
In short it gives you the ability to encapsulate and abstract the implementation from the usage, and can help you I the future to replace the implementation without a need to change the usage.
For more details see http://en.wikipedia.org/wiki/Polymorphism_(computer_science)
In that example, I don't think you can talk about an advantage (or disadvantage), because your two lines of code each do something very different.
If the type of variable a is A, then a.b refers to the field b with the value 10.
But if you change the type of a to B then a.b refers to a totally different field, the one declared inside B, with the value 12.
If instead b was a method, then the one declared in B would "override" the one declared in A, which is a very different situation. e.g.
class A
{
public int b() { return 10; };
}
class B extends A
{
public int b() { return 12; }
}
And the calling code would be:
A a=new B(); //line1
//B a=new B();//line2
System.our.println(a.b());
That is, we call the method b to get the return value. Now it makes no difference to the behaviour whether the type of a is A or B. What matters is the type of object that a refers to, which is always B and hence always has the behaviour defined in B, so it will print 12 regardless.
The advantage of this is that you can have a collection of objects (e.g. various kinds of vehicle) and they can be a mixture of cars, boats, trains etc. Each has its own implementation of the start method, so you can treat them all the same way.
Although generally it's clearer to define such methods in an interface, rather than a class. There is no general way to start a vehicle, so no reason to have a base class that has a meaningless implementation of start. Instead you just use an interface to declare the "shape" of the method without giving it any implementation.
Please tell me why i am getting ClassCastException in this case
I have type casted , the source of B class to A as shown below , but why i am still getting ClassCastException here .
public class A extends B
{
}
public class B {
public String getData() {
return "B";
}
}
public class Main {
public static void main(String args[]) {
A a = new A();
B b = new B();
a = (A) b;
System.out.println(a.getData());
}
}
It becomes more obvious if we play with different classnames:
public class Car extends SomethingWithWheels {} // was A extends B
public class SomethingWithWheels {} // was B
public class Train extends SomethingWithWheels {} // aahh, some C extends B
Now, lets cast again:
SomethingWithWheels somethingWithWheels = getItFromSomewhere();
Car car = (Car) somethingWithWheels;
The compiler has to complain, because somethingWithWheels (B) could be a Train instance (C), which can't be cast to Car (A).
You can't cast a base class to derived class. You can do the other way round though.
Because your instance "b" is not of type A (B does not extend A), so when you cast "b" to A it fails.
The opposite would work (casting an instance of type A to type B)
Because an instance of B is not an instance of A. It's really that simple.
If you create an instance of A, it's also a B - because that's what the subclassing means. However, if you create an instance of B, that is not an A, and can't be assigned/cast as such.
The only time you can cast is if the run-time class of an object is compatible with the type you're trying to cast to. You can't change the class of an existing object - which is what I think you might be trying to do here - only tell the compiler "look, I know it's really something more specific".
So as a counter-example, the following would work:
public static void main(String args[]) {
B b = new A();
A a = (A) b;
System.out.println(a.getData());
}
In this case, the variable b is declared to hold a reference to a B. It turns out that you populate it with an instance of A, but for the rest of the program the compiler isn't allowed to assume that b is an A, because it's not guaranteed. Since you know it's an A in your specific case, you insert the cast, which causes a run-time check that the object actually is an A. This succeeds, and from that point on you can call methods specific to A on your a variable.
In this case however there is no reason at all to do any casting - there are no extra methods available on the subclass that you'd need to call, and no methods which only take an A but not a B. Even if A overrode getData to do something different, you would still get this behaviour if invoking through a B reference.
You are downcasting and you try to cast a supertype to a subtype, thats why it does well during compilation but fails at runtime with ClassCastException.
You can call:
System.out.println(a.getData());
after removing the line where you try to cast the types