I have a class A and a class B which extends class A
class A{
protected String x = "";
Method (){
x = "val";
}
}
class B extends A{
// Uses x in a method
}
If I write Junit test case for a method in class B, I get value of x as an empty string "" as set while declaration. Is there a way to set the value for x to "val" while testing class B method?
Given the new scope of the question, you should be able to set x by creating an object of type B (bObject) then calling Method() from A.
B bObject = new B();
bObject.Method();
This would set X given the methodology you show in your question. You could also say
B bObject = new B();
bObject.setX(str);
Where str represents whatever you want x to be for your test case. This assumes you have x set up with a getter and setter in A, which is generally best practice.
Related
This question already has answers here:
Does polymorphism apply on class attributes in Java?
(8 answers)
Closed 4 years ago.
I have the following program :
class A{
int b = 50;
}
class B extends A{
int b = 20;
}
public class Maini{
public static void main(String[] args){
A a = new B();
System.out.println(a.b);
}
}
and the result is 50 and I would like to know why?
before I run the code I am pretty sure that the result should be 20.
This has nothing to do with how constructors work.
Note that the member variable b in class B does not override the member variable b in class A. Only non-static, non-private methods can be overridden. Member variables cannot be overridden.
If you have an instance of class B, then it actually has two member variables called b: one in the superclass (A) part of the object, and one in the subclass part (B).
The reason that you see the value 50, which is the value of b in the A part of the object, is because the variable a in the main method is of type A. If you change this to B, you'll get 20:
B a = new B(); // instead of A a = ...;
In the statement
A a = new B();
You are calling Bs constructor in an object of type A
In your program, you have given no constructor to B, so it looks to A.
In A, the value of int b is 50 and an object is of type A, hence the value is chosen as 50
If you had a constructor in B e.g.
B() { b = 20;}
the value would be 20.
You think that you are creating a B but you have not written any constrcutors for the class B so it looks to the super() constructor which is it's parents (A). So you now have an object of A. If you are curious about why A's object isi being created while there is no constructor to it too. A calls to it's super constructor too which is Java's Object Class's constructor.
I hope that I could make this point clear.
use a intellitrace enabled IDE for better experience of coding.
1st of all you'l hav a default constructor if you are not imposing on it.
Secondly you are defining an object of type 'A' not 'B'. if you want the output as 20 then you hav to include this B() {int b = 20;}.
Here in this code Sniplet there is no constructor in Any class.
So JVM will create no argument default constructor in all classes.
While you are Running this then .
In the below code you
a is referring class A and having object of class B
A a = new B();
So here the Object a will have class A 's variable value.
and Class B object value as its calling Class B 's default constructor(new B();)
If Class A and B have same Method like below Example:
class A{
int b = 50;
void method(){
System.out.println("Method of A class");
}
}
class B extends A{
int b = 20;
void method(){
System.out.println("Method of B class");
}
}
public class Maini{
public static void main(String[] args){
A a = new B();
System.out.println(a.b);
a.method();
}
}
Then a.method() will print
50
Method of B class
as a is have Class B 's object.
When you write A a = new B() the object a is type A. This is why you're getting b = 50. If you want to get b = 20, you need to declare a as a B class
Hope it's clear enough.
Best
I cannot easily verify 2 individual and unique call of a sub type class to a method which takes a supertype
I have a scenario that acts like this...
Both B and C extend abstract type A
With
public class X {
public String doSomething(A a){
return "";
}
}
Test
#Test
public void testExtensionVerify(){
X x = mock(X.class);
B b = new B();
C c = new C();
x.doSomething(b);
x.doSomething(c);
verify(x, times(1)).doSomething(any(B.class)); //fails.
}
verify times(1) fails... It sees 2 calls instead of 1 probably because B's reference in the method signature is the super type A.
The problem is that I cannot verify each call uniquely
I know that I can swtich to eq(b) and eq(c) instead of any() but I have no handle to them in my real case as they are created in the Object under test. Another option might be to do a ArgumentCaptor and test the instance but its annoying.
Any other solutions?
You can use isA:
verify(x, times(1)).doSomething(isA(B.class));
http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/Matchers.html
The any family methods don't do any type checks, those are only here to avoid casting in your code. If you want to perform type checks use the isA(Class) method. This might however change (type checks could be added) in a future major release.
public class XTest {
#Test
public void testExtensionVerify(){
X x = mock(X.class);
B b = new B();
C c = new C();
x.doSomething(b);
x.doSomething(c);
verify(x, times(1)).doSomething(isA(B.class));
verify(x, times(1)).doSomething(isA(C.class));
}
}
I don't understand how exactly it works.
We have two class A and B. Class B extends A.
Class A have x attribute, and test method which modify this attribute.
Class B have x attribute, and test method which modify this attribute.
public class A {
int x;
public void test() {
this.x = 1;
System.out.println("A" + getX());
}
int getX() {return x;}
}
public class B extends A {
int x;
public void test() {
this.x = 2;
System.out.println("B" + getX());
}
int getX() {return x;}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.test();
System.out.println(a.getX());
System.out.println("point 1");
a = new B();
a.test();
System.out.println(a.x);
}
}
Output:
A1
1
point 1
B2
0
My prediction about last line of output was 2, but is 0. Why is 0?
Let's understand these lines of code:
a = new B();
a.test();
System.out.println(a.x);
You create a new object of B. It will re-initialize the variable - A.x = 0 and B.x = 0.
Then you invoke a.test(), which will call the overridden method test() in class B, which will set B.x to 2 using this.x = 2;. Note at this point, A.x is still 0.
Then you access a.x, which will access the field x in class A. The fields are not polymorphic. You don't override fields, but you hide them. The variable x in B hides the variable x in A.
If both A and B have a member named x, the one in B will block access to the one inherited from A. Remove the int x; declaration from B, or explicitly use super.x, if you want to reference the one in the parent class.
Starting from begin.
When you write
A a;
You say to JVM please reserve me in memory an address for something that fits A.
after when you do
a = new A();
You say to JVM, create a new object of class A and save the address to it under a
when you do this;
a.test();
You say to JVM, go to memory address a and from object there invoke method test().
Next thing what you do is this:
a = new B();
You say to JVM, create a new object of class B and save the address to it under a. No error here as B fits A as is a child class.
(You loose the connection with object of class A ass you changed it to B).
next operation is
a.test();
you also know this, but this time under address a is instance of class B. This time JVM search for the method in class B, if not fond then will search in class A.
I think you should start over with the Inheritance/Polymorphism concepts first.
But to make it clear: You have an object "a" which is declared as with type "A". Now, when you call the method test (which is overriden inside B in this case), the JVM calls the actual objects method. So, before "point 1" a.test calls A's test method, after "point1" it calls B's test method.
The problem is that this feature (called polymorphism) works only on methods. Whilst when you call an instance variable (as a.x) , the JVM calls the declared object variable. In this case is A. If you make a cast first, you'll get the right value: ((B)a).x
Note, the difference between actual and declared object is based on the type after the "new" operator (like new B()) and that in the object declaration
In a situation like this:
class A{
public int x = 4;
public void s3(){
x = 3;
}
public void f(){
x = 8;
s3();
}
}
class B extends A{
public int x = 5;
public void f(){
x = 10;
s3();
}
}
A a = new B();
B b = (B) a;
a.f();
System.out.println(b.x);
System.out.println(a.x);
a.f() calls the f() of the class B, then f(), after an assignment, calls the s3() function. At this point, s3() is only defined in A and when it assigns the value 3 to x, x is the copy of the variable owned by the class A. Why s3() doesn't use the x declared in B? In theory, B shouldn't has its own copy of s3() function inherited from A? (so the s3() inherited from A in B should use the x declared in B)
You have a misunderstanding of what you should be doing in inheritance. extends is a reserved word that was wisely chosen. The point of B extending A is to say that B is a subset of A with additional attributes. You're not supposed to redefine x in B; A should be handling x. By redefining x in a subclass, you're hiding the superclass' field x (this is true even if x refers to different variable types).
A a = new B();
System.out.println(a.x); //4 makes sense, since we are of class A
B b = (B) a;
System.out.println(b.x); //5 makes sense, since we are of class B
a.f();
System.out.println(a.x); //3 makes sense, since a.f() calls s3(), which sets A's x to 3
System.out.println(b.x); //10
The 10 follows from printing b's x, which is assigned to 10 with the call of a.f(), which then calls s3() which is why the 3rd example prints 3. To see what I mean look at this:
public void f()
{
x = 10; //sets B's x to 10
s3(); //calls A's s3(), which sets A's x to 3.
}
Because it is the same. You do not have two copies ("instances") of the object, only one.
Since the one you create is a B instance (new B()), it will be used the methods as defined in B. Of course, when no methods are defined in B it will use the superclass methods implementation.
So, you only have an x attribute and s3 forces it to be 3. It works ok.
Why s3() doesn't use the x declared in B?
Generally, methods in a parent class cannot see member variables in a child class.
I think doing just this:
B b = new B();
b.f();
is enough to reproduce at least part of your confusion. Here is what f() looks like in B:
class B extends A{
public int x = 5;
public void f(){
x = 10;
s3();
}
}
f() is equivalent to:
public void f(){
this.x = 10;
this.s3();
}
So calling b.f() means f() is equivalent to:
public void f(){
b.x = 10;
b.s3();
}
Next, what happens inside the s3() method in A? s3() looks like this:
public void s3(){
x = 3;
}
and that is equivalent to:
public void s3(){
this.x = 3;
}
'this' is the object that called the method, which from the last example of f() you can see is b. So s3() is equivalent to:
public void s3(){
b.x = 3;
}
So b.x gets overwritten with 3...uhhhhm not so fast!
An instance of B also inherits an x from A, it's just that inside B it so happens that B's x shadows the x from A. As a result, the f() method in B assigns to the x from B. Inside s3() however, the x that b got from A is not shadowed anymore, and as far as A is concerned there is only one x--the one from A. In other words, the lookup for b.x takes a different path depending on what class that statement appears in.
After s3() executes, the end result is that b has two x's with two different values. Inside methods in B, the x from B will be visible, and inside methods in A, the x from A will be visible. Inside methods in B, it is possible to get at the the x from A by using super.
In theory, B shouldn't has its own copy of s3() function inherited from A?
Don't think in terms of copies. Think in terms of pointers from class to class, and pointers from classes to lookup tables. Typically in computer programming, each instance has its own instance variables but methods are shared by all the instances in a class.
I have an abstract class A with 1 method called public int get(int x, int y).
Classes B,C,D have 1 method which are all same and they extends to the abstract class A.
In a class Car, the Car constructor receives String argument type that should be used to decide which one of B, C, D have to be used in the class.
Apparently, I am using if...else conditional statements based on the type to do it.
So the codes look like
if(type.equals("B")){
A = new B();
} else if(type.equals("C")){
A = new C();
} //and so on..
Is there any elegant way that I can use string argument just as it is to decide which one of 3 classes to use?
You could use the interface / abstract class as an argument in the constructor instead of using a String.
public Car(A a) { this.a = a; }
And then elsewhere:
B b = new B();
new Car(b);
This is called dependency injection.
You can use Class.forName(String) to get a Class object and then instantiate it using newInstance()