class A is abstract and class B extends class A
now class A reference can hold object of class B,that is
A aObj = new B();
and assume class B has some extra methods....
like
class A
{
public show();
}
class B extends A
{
public show(){}
public method1(){}
private method2(){}
}
now tell me what things variable aObj can access from class B
can it access everything?
aObj only sees the public show() method. If you cast aObj to B, you can then access public method1(). public method2() is only accessible to the implementation of B.
For reference and completeness, here's a list of the possibilities:
A aObj = new B();
aObj.show(); // Works
aObj.method1(); // Error
aObj.method2(); // Error
And with casting to B:
B bObj = (B)aObj; bObj
bObj.show(); // Works
bObj.method1(); // Works
bObj.method2(); // Works inside bObj, but error otherwise
aObj can only use show() as the compiler thinks aObj is of type A, and the only known method of A is show().
If you know that you actually have a B you can cast that object to a B:
if (aObj instanceof B.class) {
B bObj = (B) aObj;
bObj.method1(); //OK
} else {
log.debug("This is an A, but not a B");
}
aObj.show();
Related
public class A {
public void m1() {
System.out.println("A m1");
}
}
public class B extends A {
public void m1() {
System.out.println("B m1");
}
public void m2() {
System.out.println("B m2");
}
}
public class Result {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*A a = new A();
a.m1();
B b = new B();
b.m1();
b.m2();
*/
A ab = new B();
ab.m1();
}
}
In the above code, I have a Class A and Class B that extends Class A. In class C I am creating the object of class B and it's been assigned to class A. when I try to call ab.m1() it calling the method in class B.but when I try to call ab.m2() i get compile time error. I am not understanding why class B method is called during ab.m1(). can someone help me in understanding the concept much better.thanks in advance.
A ab = new B();
You create a reference of type A and point it to an object of type B. This is valid and legal because B extends A, so an object of type B IS-A type A. That's why, when you call ab.m1(); you're calling the method defined in B. Your object type is B, so it overrides the method defined in A.
However, you can't call ab.m2() because the reference is type A, and knows nothing about new methods defined in B that weren't included in A. The reference only has access to the things defined in A (and anything that it might inherit from its super types, like Object).
B -->A// B is-a A
A ab = new B()//object of B is created and reference variable is type of Super type as A is super class of B
since ab.m1() is type of A class and can be accessible through super variable.
ab.m2() is type of B class and can not be accessed using super type reference, thats where down casting comes into picture.
try:
B a = (B)ab;// down casting
a.m1();
a.m2();
now you call both method of B class.
I decided to simulate this example code from Android app:
TextView txt = (TextView) findViewById(R.id.activity_display_message);
findViewById returns View object and then we cast it to a TextView one(TextView is a subclass of View)
It seems I have misunderstood how it works. I was expecting this code to work because C extends B and therefore I should downcast a B object to C.
But I am getting an exception at runtime that I can't cast B to C.
So can anyone explain where I am wrong? And why the Android sample works?
public class A{
public static void main(String[] args){
B b = new B();
b.f();
C c = (C)b;
}
}
class B{
public void f(){
System.out.println("Class B");
}
}
class C extends B{
public void f(){
System.out.println("Class C");
}
}
Cast operation lets you change the static type of your object, which is another way of saying "tell the compiler what you know about the type of the object being cast."
If you have a variable of type B which contains an object of type C, you are allowed to cast that variable to C:
B b = new C();
C c = (C)b; // works fine
This is allowed precisely because b's object is actually a C.
When the object referenced by b is not a C, the compiler will catch your mistake, and throw a cast exception:
B b = new B();
C c = (C)b; // throws class cast exception
The difference between a successful and unsuccessful is decided by the actual type of the object at runtime. The code that works manages to cast a View to TextView because the variable which is statically typed as View actually references a TextView at runtime.
In java, you cannot assign a superclass reference variable to a subclass reference variable without a cast of the subclass type. Examples can find in When is an explicit object reference casting is required?. The compiler is happy when you explict cast the superclass reference to subclass reference, but the compiler does not care what the actual object holded by the reference. Does it actually have a superclass object, or just a superclass reference holding a subclass object? No answer from compile time but it has to answer this quesiton.
You can not just take a parent object and suddenly turn it into a child though. The parent object is not an instance of the subclass. If the actual object holded by the reference is a superclass object, casting it to a subclass reference result in a compile time error.
In your case B is parent class and C is its child.
class SuperClass {
// ...
}
class SubClass extends SuperClass {
// ...
}
public class Program {
public static void main(String[] args) {
// case 1: actual SuperClass object
SuperClass p1 = new SuperClass();
// case 2: SubClass object is referred by a SuperClass reference
SuperClass p2 = new SubClass();
SubClass s1 = (SubClass) p1; //run time error
SubClass s2 = (SubClass) p2; //OK
}
}
In Android findViewByIdreturns instance of View Class. Which is a direct superclass of TextView and other view elements.
So if you want to replicate something like that, then you can do something like this:
class Test {
public static void main(String args[]) {
A a = new A();
C c = (C)a.getViewByid('c');
c.f();
}
}
class A {
public B getViewByid(char c) {
B b = null;
switch (c) {
case 'b':
b = new B();
break;
case 'c':
b = new C();
break;
default:
b = new B();
}
return b;
}
}
class B {
public void f() {
System.out.println("Class B");
}
}
class C extends B {
public void f() {
System.out.println("Class C");
}
}
I have a function in Class A which I would like to change the value of a field in Class B.
Class C has my main() and creates a new instance of class B and Class A. Class A is from an API and one of their functions is a listener function. I would like for that listener function to be able to change the field of Class B, but when I write the code for the listener function, it doesn't recognize Class B's instance.
How do I reference that instance?
Example code:
public class A {
public void listenermethod(){
//can't reference Binstance <-------
}
}
public class B {
B.field = 1;
}
public class C {
A Ainstance = new A();
B Binstance = new B();
}
You should give A class a private B field, and then you can call the public methods from B on this field as needed. If you need to create both A and B instances in a separate class (C) you should give your A class a public void setB(B b) setter method.
A.java
class A {
private B b;
public void setB(B b) {
this.b = b;
}
public void listenerMethod() {
if (b != null) {
b.someBMethod();
}
}
}
C.java
public class C {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.setB(b);
a.listenerMethod();
}
}
You have to be able to modify both class C and class A. Rewrite the class A method to
public void listenermethod(Binstance theB){
theB.something = "some_value";
}
Now when you call class A, pass in the Binstance. If you can't modify class A, then your task can't be done.
An instance by definition belongs to an object. Therefore, your class A must either have an object of class B as a member:
Class A{
private B instance_of_b;
}
now you can access B members like this:
instance_of_b.member
or the field belonging to class B could be static and then A could access it through the class.
B.member
Also make sure you know the meaning of accessor keywords (private,protected,[friendly],public).
So I want to check to see if a class is assignable to a super class that contains many sub classes, something like this
public class A {
public A(){ }
}
public class B extends A {
public B(){ }
}
public class C extends B {
public C(){ }
}
public static void main() {
A a = new C();
boolean whyAmIFalse = a.getClass().isAssignableFrom(B.class);
}
Why does this return false? Obviously it can be assigned to class B as
B b = (B)a
does not return an error, so why is this returning false. Is it not the function it describes itself as? Is there a function that does accomplish what I want it to me (ie I am that class or a subclass of it)?
If what you want to do is test whether or not a's actual type is B or a subtype, you've got it backwards: it's
B.class.isAssignableFrom(a.getClass());
This is because getClass() returns the actual class, not the declared class of a variable -- a.getClass() will return the class C (C.class), which is the actual class of the object that was assigned to the variable A a and you indeed can't assign a B to a C
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#getClass()
Because class B doesn't extend/implement class C, which is what isAssignableFrom() tests. An instance of class B might be an instance of class C, as per your example. To test that, use 'instanceof'.
I have a Java class B with an inner class C. Some methods of B accept an instance of C as parameter but I only want to accept C instances created by the proper instance of B. Is there a way to do this validation at compile time?
Example
C c1 = new C();
B foo = c1.getB(); // foo was created by instance c1
C c2 = new C();
c2.method(foo); // I want a compiler error here.
My case
Have a class names Map which hold a matrix of instances of the inner class MapArea. The nice thing about this scheme is that I can validate the xPos, and yPos fields at the constructor so no invalid Areas for a given map are built. The map as a method distanceFrom(MapArea startingPos, MapArea toLocation, MapArea... otherLocations) and I was trying to avoid to validate the map area arguments again.
If this is really the behavior you want, method() should really be defined in the inner class.
In other words, instead of:
public class C {
//...
public void method(B b) {
this.x = b.y;
//...
}
//...
public class B {
//...
}
//...
}
It should be:
public class C {
//...
public class B {
//...
public void method() {
C c = this.C;
c.x = this.y;
//...
}
//...
}
//...
}
Of course, this wouldn't solve the problem if, for example, you wanted public void method(B b1, B b2, B b3), where all three instances of B are enclosed by the same instance of C.
A compile error won't work, but you can at least throw an exception:
public class C
{
public static void main (String [] args)
{
C c1 = new C();
B b = c1.getB();
c1.useB(b); //OK
C c2 = new C();
c2.useB(b); //throws IllegalArgumentException
}
public B getB() { return new B(); }
public void useB(B b) {
if(b.getC() != this)
throw new IllegalArgumentException();
//...
}
private class B
{
public C getC() { return C.this; }
//...
}
}
There's no way (AFAIK) of doing this at compile time.
At runtime you can do it by having the outer instance's factory method pass a reference to itself to the inner instance's constructor.
The inner class would need to store that reference, such that the outer class can check whether it created that instance or not:
public class C {
public class B {
private C parent;
private B(C parent) {
this.parent = parent;
}
public C getParent() {
return parent;
}
}
public B getB() {
return new B(this);
}
public void method(B b) {
assert(this == b.getParent());
}
}
Actually, as Kip's concurrent answer shows, B can access C.this to get the parent object so there's no need to store the parent reference. However the method above would be necessary if C wasn't actually an inner class.
If you make the constructor of the inner class (C) private, I believe the enclosing class (B) can still instantiate it while other classes cannot. This ensures that only B and C can instantiate C.
Edit: I've verified that with a small mockup. Make the inner class constructor private, and then only the inner class (C) or the enclosing class (B) can instantiate it.
See http://tns-www.lcs.mit.edu/manuals/java-1.1.1/guide/innerclasses/spec/innerclasses.doc6.html for more. In particular: "Access protection never prevents a class from using any member of another class, as long as one encloses the other, or they are enclosed by a third class.".
There's no compile-time way to guard against instance-specific usage. Your best bet is probably throwing an Exception when the usage in incorrect. Another option you have is to have the parent class to have a Map of instances of the inner class, and to have other classes tell the outer class to operate on the inner class not by the instance but by some other references. This will work with other classes don't need to do anything directly with the inner class.