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.
Related
class A {
public int a = 100;
}
class B extends A {
public int a = 80;
}
class C extends B {
public int a = 10;
public void show() {
int a = 0;
System.out.println(a);
System.out.println(super.a);
System.out.println(((A) this).a);
}
}
What does ((A) this).a in the line System.out.println(((A) this).a); do?
Is it upcasting/downcasting thisor is something else happening here?
I also tried System.out.println(this); and System.out.println((A)this); and they both have the same output. What exactly is happening here?
In the java programming language, we have classes. When we write java code, we create instances of those classes, for example:
Object o = new Object();
Object is a class. Writing new Object() creates an instance of that class. The above code declares a variable o and assigns it [a reference to] an instance of class Object.
In the terminology of the java programming language, we say that variable o has type Object.
In the code in your question, a variable that is assigned an instance of class C, really has three types.
It has type C.
It has type B since B is the superclass of C.
It has type A because it indirectly extends class A also.
In the context of the code in your question, this is a special variable whose type is C. Writing (A) this is telling java to relate to the variable this as if its type is A.
Class A cannot access its subclasses. Hence it is only aware of its class member a. Hence when you write this line of code...
((A) this).a
You are accessing the member of class A only.
System.out.println(a);a is the one from the show method of your C class → a = 0
System.out.println(super.a);a is the one from the super-class of C, which is B → a = 80
System.out.println(((A) this).a);First, you cast your C instance (this) into A, then you call a which is a member of the A class → a = 100
There is also something to consider : method will always take the more specialized one (except if super is used), where field will be taken directly from the type referenced (even if there is an extending class).
For example, if I add getA() in each classes :
class A {
public int a = 100;
public int getA(){
return a;
}
}
class B extends A {
public int a = 80;
public int getA(){
return a;
}
}
class C extends B {
public int a = 10;
public int getA(){
return a;
}
public void show() {
int a = 0;
System.out.println(a);
System.out.println(super.a);
System.out.println(((A) this).a);
System.out.println(getA());
System.out.println(super.getA());
System.out.println(((A) this).getA());
}
}
class Scratch {
public static void main(String[] args) {
new C().show();
}
}
I get the following output :
0
80
100
10
80
10
Which means that in the case of the method, except in the case of super.getA() which explicitly goes to the superclass, casting your C into a A doesn't change much for methods, as it impacts the field.
If you write something like obj.a, obj.getA() or someMethod(obj), Java somehow has to find the actual field or method to be used, based on the type or class of obj. There are two distinct dispatch mechanisms involved (plus the special construct super).
Dynamic dispatch (polymorphism, overriding): This is used when calling an instance method on the object, as in obj.getA(). Then the runtime class of the obj is examined, and if this class contains a getA() method, this is used. Otherwise, the direct parent class is examined for a getA() method, and so on up to the Object class.
Static dispatch: In cases like obj.a or someMethod(obj), the runtime class of obj doesn't matter. Involved is only the compiler, and from his knowledge of obj's type, he decides which field or method to use.
super dispatch: If you write super.getA() or super.a, your getA() method or a field is ignored, and instead the next-higher class in the hierarchy is used that contains such a method or field.
In your case you have 3 fields plus one local variable, all with the same name a. (By the way, it's a very bad idea to have such name conflicts in professional code.) We are inside a method show() declared in the C class. Let's have a look at some different expressions and what they mean here:
a references the local variable a. There's no dispatch needed, it's just that local definitions take precedence over fields.
this.a is a static-dispatch expression, so it's important what the compiler thinks about the type of this. And that's always the class where this code has been written. In your case, it's class C, so the field a from class C is used, the one being 10.
super.a is a super-dispatch expression, meaning that the a field from this class C is ignored and the next higher one taken (the one from B, in our case).
((A) this).a is static dispatch, but the (A) casting has a significant effect. The expression before the dot originally comes from this, being of type C, but the (A) cast tells the compiler to believe it were of type A. This is okay, as every C also is an A, by inheritance. But now, static dispatch sees something of type A in front of the dot, and dispatches to the a field from the A class, and no longer from C.
getA(), this.getA() and ((A) this).getA() are all dynamic-dispatch examples, all giving the same result. The method called will be the one based on the runtime class of this object. This will typically be one defined in the C class. But if show() was called on an object of a subclass of C, e.g. D, and D had its own getA() method, that one would be used.
super.getA() is a case of super-dispatch, it will call the getA() method next higher up in the class hierarchy from the current class, e.g. B.
System.out.println(this);
And
System.out.println((A)this)
These two prints the object reference to class C with toString() method.
System.out.println(((A)this).a);
This is upcasting, child object to parent object.
Given a base class Base, that's say A, B, C extends Base.
If there is a specific method m() only in C. To call m() , you should first determine if the given class is type of C , one of the way is to use:
otherMethod(Base b){
if(b instanceof C)
b.m();
}
But I'd like to use:
otherMethod(Base b){
b.m();
}
This means I have to pull the m() method up to the super class Base and only implement it in class C. But m() has no relation for class A and B and should not belong to them. This is not intuitive for code readability. So is there a better design of this case to use polymorphism and without non-reasonable method position?
If a class C has any specific method, same should not be part of Base class. To call the method m(), you will have to check the type of instance using instanceof operator and then cast your Base class to C and then call method m() like below
otherMethod(Base base){
If(base instanceof C){
C c= (C) base;
c.m();
}
}
Further, as others have already cited out the example of Collection and List, if your class C needs to have specific method, you should create one interface, lets say its called Child which should extend the Base interface. The other 2 classes should implement Base interface. And class C should implement Child interface.
Now, when you are designing Base interface, definitely, you won't know what specific methods other classes could implement. Therefore, you should not be calling any specific method in your otherMethod as well.
If you have Java 8 and performance is not an issue (which would be the case if you want to render 10000 shapes at 60fps) then filter the collection.
Assuming a Collection<Shape> shapes:
shapes.stream()
.filter(s -> s instanceof C)
.forEach(c -> ((C)c).m());
nb. You should never declare behavior (i.e. methods) in classes or interfaces that have nothing to do with it. In ernest_k's example, don't put get(int) in interface Collection just because List uses it. This keeps the class structure clean and understandable. Instead change the usage of the class structure, either the hard way (with type checking and casting) or by separating different subclasses in different collections (so you don't have to check types).
If you had this:
Collection<A> justA;
Collection<B> justB;
Collection<C> justC;
then you wouldn't have this problem, but then you would have another (probably worse) problem, that every time you add another subclass (say D) you have to change code all over the place, and there is the risk you forget to change it somewhere.
Don't infect the design further than adding a Base.visit(IVisitor v) {v.visit(this);}
interface IVisitor {
void visit(Base b);
}
Then write the IVisitor you need (here with the instanceof C)
Of course, you could just use Consumer instead of your own visitor interface. I just meant to be clear.
Another option is to use overriding methods. When calling otherMethod() on a Base object, it will call the doThings() defined in Base unless it is an instance of C, which has overloaded the doThings().
public class Base {
public void doThings() {
// nothing happens
}
public void otherMethod() {
doThings(); // will call method above if instance is Base object, will call method below if C object
}
}
class C extends Base {
public void doThings() {
System.out.println( "Things actually get done" );
}
}
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.
Hopefully this question hasn't already been asked. I've had a look around but haven't found a similar post.
Experimenting in Java I've noticed that there is no restriction on having duplicate method signatures in a nested class, which seems counter-intuitive.
For example, if I create class A containing a method with the signature int x() and later add a nested class B containing an identical method, the compiler seems to have no problem with it. My initial assumption was that it would complain that x is already defined. Perhaps I'm missing something obvious that explains why this is allowed?
class A {
int x() {
return 1;
}
class B {
int x() {
return 2;
}
}
}
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
Edit: I appreciate that the core of the question is the same as this post, however, I was more interested in understanding why this behaviour is allowed as it wasn't immediately clear to me.
Where a class is defined doesn't matter so much. Keep in mind, in the end you have
class A { int x()
and
class A.B { int x()
Two (almost) independent classes. The only relationship that we have here is that any instance of B needs an "enclosing" instance of A to which it belongs (because it is a non-static inner class).
And of course, you can access the "enclosing" A "stuff" from within B, for example using A.this.x().
This should be available somewhere in the JLS - but ultimately it boils down to scope. Each of them has a different scope - thus the compiler does not complain.
Why would the compiler complain? They are two different classes, they just happen to be nested.
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
A.this.x()
At first method signature is not the combination of return type and method name it is method name and parameters.
if you call x() it will run x() inside the B
A.this.x(); it will run x() in A
Its scope, it's similar to have an instance variable called foo and then a local one in the method called foo as well.
Its worth reading about scope in java
Inner class in java can access all the members (i.e variables and methods) including private one, but outer class can not access member of inner class directly.
To access x() method of class B inside class A you can either create B's instance and call it or call like this A.this.x();
To access x() method outside class A you can do something like this:
B b = a.new B();
b.x();
If you are using non-static nested class (inner class) then it wouldn't be able to access to x method of B class from other classes. But if you are using static nested class you will be able to access that method from other classes. Example:
public class A {
int x() {
new A.B().x();
return 1;
}
static class B {
int x() {
new A().x();
return 2;
}
}
}
public static void main(String[] args) {
A a = new A();
a.x();
B b = new A.B();
b.x();
}
I hope this example answering your question... ☺
B is nested inside A. According to scope rules we can do the following:
class A {
int x() {
return 1;
}
class B {
int x() {
return 2;
}
int xOfA(){
return A.this.x();
}
}
public static void main(String[] args) {
final A objA = new A();
final B objB = objA.new B();
System.out.println(objA.x());
System.out.println(objB.x());
System.out.println(objB.xOfA());
}
}
that is because B is visible from an instance of A.
Moreover B can reference methods in the containing class through their full paths.
For example, if I create class A containing a method with the signature int x() and later add a nested class B containing an identical method, the compiler seems to have no problem with it. My initial assumption was that it would complain that x is already defined. Perhaps I'm missing something obvious that explains why this is allowed?
When you define something in a nest scope which is otherwise in an outer scope, this is hiding.
What is important is that -: The version of a method that is executed will NOT be determined by the object that is used to invoke it. In fact it will be determined by the type of reference variable used to invoke the method
Subsequently, is there any way to access class A's method x from within the scope of class B, or is it permanently hidden by the method x of the local scope?
So as it is clear from above we can access it using class name, eg A.x
Hope this helps!!
I have the following codes:
1. public class Tester
2. {
3. public static void main(String[] args)
4. {
5. A a = new B();
6. System.out.println(a.getClass()); //Prints class B
7. System.out.println(a instanceof A); //Prints true
8. System.out.println(a instanceof B); //Prints true
9. System.out.println(a.valA); //Prints 1
10. System.out.println(a.valB); //Compilation error
11.
12. }
13. }
14.
15. class A
16. {
17. int valA=1;
18. }
19.
20. class B extends A
21. {
22. int valB=2;
23. }
At line 6 it shows that a is of type class B. However when it reaches line 10, the compiler produces an error: location: variable a of type A.
So my question is: What exactly is the class type of a now? Why getClass() shows that it is of type class B, yet the compiler complains it as type A during compilation?
Further more, since a instanceof B is true, why can't I access valB?
To make things clearer:
EDIT: I ran this statement: System.out.println(a); and the output was B#36d98810 which somehow proves that the toString() method of class B was executed. Since variable a can access the toString() method within class B, why can't it access valB which also resides in class B?
Professor Jonathan Shewchuk from UC Berkley explains about shadowing over here. Start at 18 minutes. (If the link changes just google search for CS 61B Lecture 15: More Java)
To answer your question in short there are two types for a variable, static type and dynamic type.
Static type is its Type at compile time
Dynamic type is its Type at run time.
In your example
A a = new B();
The static type of a is A and the dynamic type of a is B.
In Java a variable gets its non static methods from dynamic type
(if the method exists in both the parent and child class)
and
its fields and static methods from the static type.
This is true in C# only if the method is overridden in the sub class
Update:
The line
a instanceof A
tells you whether the dynamic type of a is of type A OR a subclass of A
Update 2:
AN example that illustrates this
public class PlayGround {
public static void main(String[] args) {
Animal a = new Dog();
System.out.print(a.name);// displays animal
System.out.print("\r\n");
a.MakeStaticSound();// displays static animal sound
System.out.print("\r\n");
a.MakeSound();// displays bow wow
}
}
class Animal {
public String name = "animal";
public void MakeSound() {
System.out.print("animal sound");
}
public static void MakeStaticSound() {
System.out.print("static animal sound");
}
}
class Dog extends Animal {
public String name = "dog";
public void MakeSound() {
System.out.print("bow wow");
}
public static void MakeStaticSound() {
System.out.print("static bow wow");
}
}
Please note that the more readable and preferred way to call a.MakeStaticSound() is Animal.MakeStaticSound()
a is not an object. It's a variable.
The type of the variable is A. The type of the object that the value of the variable refers to at execution time is B.
The compiler resolves everything against the compile-time type of the expressions involved - the variable in this case. When trying to resolve the name valB within the compile-time type of A, it fails to find anything - hence the error.
You need to keep in mind that compilation and execution are two different processes that happen at different times and have different kinds of information available to them. The compiler has to predict the future -- it has to decide whether it can guarantee that your code will make sense in the future, at runtime. It does this by analyzing the types of the objects in your code. The runtime, on the other hand, just has to inspect the current state of things.
When you read the line A a = new B(), you are inferring more information about the a local variable than the compiler is. The compiler basically just sees this as A a = <some expression>. It does not take note of the contents of the expression that's used to produce the value for a.
The fact that you've said A a = ... is you telling the compiler: "hey, this a thing I'm going to deal with in the rest of my program, it's just an A, don't assume anything more about it." If you had instead said B a = ..., then you're telling the compiler that it's a B (and the compiler also sees B extends A elsewhere in your code, so it knows it's also an A).
The subsequent expressions a instanceof A, a instanceof B, a.getClass(), and a.toString() are legal, from the compiler's point of view, regardless of the type of a: the instanceof operator and the getClass() and toString() methods are defined for all Objects. (The compiler does not need to predict what value those expressions will produce at runtime, just that they will produce either true or false, some Class<?>, and some String, respectively.)
But then when you come to a.valA and a.valB, the compiler actually has to do some real work. It needs to prove or guarantee that the a object will have a valA and a valB field at runtime. But since you've explicitly told it earlier to just assume that a is an A, it can not prove that it will have a valB field at runtime.
Now, later on, at execution time, the JVM has more information. When it evaluates a.getClass(), it actually looks up the concrete class that's "under the hood" of a and returns it. Similarly for instanceof B -- it looks up the concrete class and thus the result of that expression is true.
a.toString() works similarly. At runtime, the JVM knows that the thing referenced by a is actually a B, so it executes B's toString method.
This is a fundamental property of class inheritance, interfaces, etc.
Class "A" does not have a variable "valB".
If you want to use the variable "valB" in class "B" either, you should first cast Class "A" to "B"
Try :
System.out.println(((B)a).valB);
You should know the difference between object type and instance type. First is determined at compile type and at runtime it's doing the best to keep that type safe. Instance type is a class which object is instantiated.
A a; //this is an object type
new B(); //this is an instance type
A a = new B(); //all together, but a is of type A, having instance of type B.