If i define
class A {
public int a;
public float b;
public A() {
a = 10;
}
}
class B extends A {
public B() {
a = 2;
}
}
class C extends A {
public C() {
b = 2.0f;
}
}
And in main
public static void main(//...) {
A a = new A();
B b = new B();
C c = new C();
a = b; //error?
b = c; //this one too?
}
I am not sure about the first error, it looks fine. You should in future post the exact error message along it. You should never ignore error messages since they tell something about the cause of the problem. The second error is obvious, it's a type mismatch: C does not extends B, so you cannot assign an instance of C to a reference which is declared as B. To fix it, you should declare it as C, A or Object (since it is the implicit superclass of all classes).
Further, your class C doesn't compile since the constructor is named A() instead of C(), but that'll probably be a copypaste error ;)
See also:
Inheritance tutorial
Related
Here is my definition of class
class A {
B b = new B(this);
}
Is it correct to pass this keyword as parameter for member
objects creation in the class' definition?
if yes where can we use this?
It is correct in the sense that it compiles and runs.
It may be dangerous because your object is not fully initialized, so using it inside the member object's constructor may not be safe.
At a higher level, it's a bad practice to create new objects in constructor, see Injection of Dependencies pattern.
Update: this code certainly compiles:
class B {
B(A a) {
}
}
class A{
B b = new B(this);
}
If you had some kind of context object which is always created, you could use this pattern to avoid using an inner class.
So instead of this:
class A {
B b = new B();
class B {
void printA() { System.out.println(A.this); }
}
}
You could have two separate files:
class A {
B b = new B(this);
}
class B {
A a;
B(A a) { this.a = a; }
void printA() { System.out.println(a); }
}
class A
{
int a = 2, b = 3;
public void display()
{
int c = a + b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Why does the output come out as 5,5? And not 5,11?.How would the y.display() method work?
why does the output comes 5,5?
Because A.display() only knows about the fields A.a and A.b. Those are the only fields that any code in A knows about. It looks like you expect the declarations in B to "override" the existing field declarations. They don't. They declare new fields which hide the existing fields. Variables don't behave virtually in the way that methods do - the concept of overriding a variable simply doesn't exist. From the JLS section 8.3:
If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class.
You can get the effect you want by changing B so that its constructor changes the values of the existing fields that it inherits from A instead:
class B extends A {
B() {
a = 5;
b = 6;
}
}
Note that these are not variable declarations. They're just assignments. Of course in most code (well, most code I've seen anyway) the fields in A would be private, so couldn't be accessed from B, but this is just example for the purpose of explaining the language behaviour.
In class A you declare fields a and b. The method display uses these fields. In class B you declare NEW fields of the same name. You're actually hiding the old fields not "overriding" them. To assign different values to the same fields use a constructor:
class A {
A(int a, int b) {
this.a = a;
this.b = b;
}
A() {
this(2, 3);
}
int a,b;
public void display() {
int c=a+b;
System.out.println(c);
}
}
class B extends A {
B() {
super(5, 6);
}
}
When doing this:
class B extends A
{
int a = 5, b = 6;
}
you are not redefining a and b, you're creating new variables with the same names. So you end up with four variables( A.a, A.b, B.a, B.b).
When you call display() and calculate the value of c, A.a and A.b will be used, not B.a and B.b
There isn's anything called variable overriding. That is why you are getting the same result in both the cases.
The reason is that Java uses the concept of lexical scope for variable resolution.
Fundamentally, there are two possible options to resolve free variables in a function ('free' means not local and not bound to function parameters):
1) against the environment in which the function is declared
2) against the environment in which the function is executed (called)
Java goes the first way, so free variables in methods are resolved [statically, during compilation] against their lexical scope (environment), which includes:
method parameters and local method variables
field declarations in the class containing method declaration
public field declarations in parent class
and so on, up the chain of inheritance
You would see this behaviour implemented in most programming languages, because it is transparent to developer and helps prevent errors with shadowing of variables.
This is opposite to the way methods work in Java:
class A {
public void foo() {
boo();
}
public void boo() {
System.out.println("A");
}
}
class B extends A {
#Override
public void boo() {
System.out.println("B");
}
}
class Main {
public static void main(String[] args) {
B b = new B();
b.foo(); // outputs "B"
}
}
This is called dynamic dispatch: method call is resolved dynamically in runtime against the actual object, on which it is called.
When you compile your code it pretty much becomes like:
class A extends java.lang.Object
{
int a=2,b=3;
public void display()
{
int c=a+b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
public void display()
{
super(); //When you call y.display() then this statement executes.
}
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
And hence, when super calls, the method of class A is being called.
Now go to method of class A. Here int c = a + b; means
c = this.a + this.b; which is 2 + 3.
And the result is 5.
Class B declares variables in B scope, public void display() is part of A class and knows only about its own scope variables.
It's the inheritance functaionality which gives the output 5,5.
Java doesn't have anything like variable overriding. Thus, when the method display() is invoked, it accesses the variables inside the parent class 'A' and not the variables inside the subclass 'B'.
It can be explained with the same reason of why you can't print a variable declared in a subclass (and not in superclass) inside superclass method. The superclass method simply doesn't have access to the subclass variables.
However, you'll be able to print 5,11 if you have accessor methods to the fields in both the classes and you use those accessor methods to get the values instead of directly accessing using variable names. (even if the display() method is present only in superclass). This is because the overridden accessor methods are invoked (in second case) which return the values from the subclass.
Why does the output come out as 5,5? And not 5,11?
Whenever we have same instance variables (applicable to class variable as well) in a class hierarchy, the nearest declaration of the variable get the precedence. And in this case, nearest declaration of a and b from display () method is A’s. So class B’s instance variables go hidden. Hence in both cases, 5 gets printed.
How would the y.display() method work?
Another alternative is to have getter in both classes to get value of a and b.
class A
{
int a = 2, b = 3;
public int getA() {
return a;
}
public int getB() {
return b;
}
public void display()
{
int c = getA() + getB();
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
public int getA() {
return a;
}
public int getB() {
return b;
}
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Prints
5
11
Let's say I have 3 classes; A , B and C. Class A and B are in one package. C is in another package. B is having a public function that returns a boolean value.
Object of B is created in Class A and he can call the functions of Class B. But the problem is that in Class C I want to have the reference of Class B object created by Class A, I don't want to create one more Class B object in Class C.How can I get that.
Example: Class B and Class A are in same package
B.java
class B
{
public boolean fun()
{
returns boolValue;
}
}
A.java
class A
{
B b = new B(); //Creates object of Class B and can access function.
}
Class C is in another package and different project also.
C.java
class C
{
//How to get the reference of Class B object created in Class A?
}
Once I get the reference to that I am going to call the functions of Class B to get the values. I tried writing some get() which returns the object of class B but to call that function I should have the object. But I don't know how to do that. This might be easy but I am new to java and I don't know how to do that. Please do help me to solve this problem.
**UPDATE : I can't create Class A object in Class C :( **
Make class A public
publi class A {
private static B b = new B(); //Creates object of Class B and can access function.
public static B getB() {
return b;
}
}
class C
{
//I want to get the reference of Class B object created in Class A....But How??? :(
B b = A.getB(); //if it works ????
}
Classes A and B need to be public and class A needs to provide a public accessor to the required field.
public class B {
}
public class A {
public B getB() {
return this.b;
}
}
Note that in your current code structure you will not be able to automatically instantiate B from your A object outside of a method.
You can create an A object in the class description but to initialize B you'll need to use the class constructor.
public class A {
private B b = new B();
public B getB() {
return b;
}
}
public class C {
private A a = new A();
private B b;
public C() {
b = a.getB();
}
}
or, if you don't want to create A, you may make it static.
public static class A {
private static B b = new B();
public static B getB() {
return b;
}
}
public class C {
private B b;
public C() {
b = A.getB();
}
}
You have to get access in C to A class and then share B reference by field.
So you may do something like this:
class B { //your function... }
class A {
B b = new B();
public B getB() { return b }
}
class C {
A a = new A();
public B getB () { return a.getB() }
}
}
Add a constructor to class C with object b as parameter
public class C{
private B bObj;
public C(B b){
bObj=b;
}
}
call this constructor from within your A class, which will create a reference to the created B object and you'll have this ref in bObj.
I have these two classes:
public class A {}
public class B extends A {}
In the main class, I would declare:
A a = new B();
B b = new B();
What is the difference between a and b ? Is this what we called a subtyping in java?
The difference between a and b is that with a you can only use the public API that the A class provides even though its really a B type object, but with b, you can use both the A's public API as well as B's public API.
For example:
Suppose A and B are defined as follows:
// A.java
public class A
{
public void x()
{
z("X");
}
public void y()
{
z("Y");
}
protected void z(String message)
{
System.out.println(message);
}
}
// B.java
public class B extends A
{
public void a()
{
z("A");
}
public void b()
{
z("B");
}
}
And here's a demo:
// Demo.java
public class Demo
{
public static void main(String[] args)
{
A a = new B();
B b = new B();
// Can only call A's public methods
a.x();
a.y();
// a.a(); Can't use
// a.b(); Can't use
// Can call all public methods
b.a();
b.b();
b.x();
b.y();
}
}
Yes, there is difference between them. Accssibility of methods are different depends on what kind of reference you use.
A a = new B();
B b = new B();
a is a reference of Class A and b is a reference of class B. super class always can be used to point subclass object.
reference a able to access only super class method and properties
reference b able to access super class and it's own method and properties
one important thing is, ability of accessibility of function and properties will decided at runtime.
In below two cases
A a = new B();
a is an instantiation of B and of type A.
whereas in
B a = new B();
a is an instantiation of B and of type B.
The important thing to note here is that (in the first case) if you call a.someMethod(), the method of B will be called, not the method of A (this is called dynamic binding, as opposed to static binding).
This is basic inheritance. In the B b = ... case you can access all methods and variables provided from A and B but in the A case you can only use the methods and variables in the A case.
B gets typecasted into A when it is created, but that information is not required by the compiler.
public class A {
int x;
}
public class B extends A {
int y;
}
A a = new B();
B b = new B();
int c = a.x; //works
int c = a.y; //doesn't work
int c = b.y; //works
int c = b.x; //works
Remember, that you can always cast an object "downwards" in the inheritance chain. But you should not cast a object upwards because the variables for the subclass might be used even though they dont exist, for exmaple B b = new A(); So b.y is dangerous since the B object doesn't have an y variable defined.
Can someone explain to me how the two lines under the comment are compilable?
A a = new A();
B b = new B();
C C = new C();
// How can these work?
((G) a).methodG(a);
((B) a).methodG(a);
public class A {
A methodA() {
return this;
}
}
public class B extends A implements G {
B methodB(A a) {
return this;
}
public G methodG(A a) {
return (G) this;
}
}
public class C implements G{
C methodC(G g) {
return this;
}
public G methodG(A a) {
return (G) this;
}
}
public interface G {
G methodG(A a);
}
They won't work. You'll get a ClassCastException.
It will compile fine, since the compiler doesn't know for a fact that a is not a subclass of A that also implements G (for example B). However, during runtime, when you try to cast, it will fail.
And this is specifically one of the big reasons people shouldn't cast unless there's absolutely no choice. It breaks a lot of the type-safety you get with the compiler.