So let's say I have two classes.
public class example1 {
private int a;
private String b;
public example1(int a, String b) {
this.a = a;
this.b = b;
}
public int getA() {
return a;
}
public String getB() {
return b;
}
}
public class example2 extends example1 {
public example2(int a, String b) {
super(a, b);
}
#Override
public int getA() {
return 10;
}
}
Now, if I go ahead and cast example2 to type example 1.
example1 a = (example1) new example2(5, "Hi");
What will a.getA() return?
As a further question from that, if example2 looked like this..
public class example2 extends example1 {
public example2(int a, String b) {
super(a, b);
}
#Override
public int getA() {
return getAModified();
}
public int getAModified() {
return 10;
}
}
What would a.getA() return? What happens here, and more importantly why does it happen?
What would a.getA() return?
Will give you the result from example2, since your instantiated using the class example2
What happens here
example1 a = (example1) new example2(5, "Hi");
.
You are creating an instance of type example1 witn of implementation example2. And casting to example1.
Casting shows the use of an object of one type in place of another type. That's it. It won't magically convert the instantiated object to casted.
What will a.getA() return?
will execute the getA() method of example2 i.e. 10.
Even in your second case, it will return 10.
Reason here is method overriding
Its getting decided during runtime, which getA() method is getting called.
Since you are creating an object of Example2, hence in both cases the getA() of Example2 is getting called, its overriding the getA() method of Example1.
You are able to cast the object of Example2 to Example1 as it is parent class but it won't change the fact that the object is actually of Example2.
Related
class A{
int a;
public int getA(){
return a;
}
public void setA(int a){
this.a=a;
}
}
// Class B extending A class and add one additional variable
class B extends A{
int b;
public int getB(){
return b;
}
public void setB(int b){
this.b=b;
}
}
// this is the main class
class HelloWorld {
public static void main(String[] args) {
A aa;
if(runtime conditon) {
aa= new B();
aa.setA(3);
((B)aa).setB(4);
}
else{
aa= new A();
aa.setA(3);
}
}
}
How to design to solve the above problem without using casting?
sorry for asking the low-level question (I am new to java).
Since class B extends class A you can use a variable of type A to point to a variable of type B.
But if you want to use only one variable of type A (in your case aa) you cannot use a method of class B without casting the object.
Because you have to remember that when you use a variable (in your case type A) that points to a derived type use (in your case type B), you can only use the methods that are defined in class A, the rest are obscured. By casting the object to its true type you can use all of its methods.
Introduce another variable:
B bb= new B();
bb.setA(3);
bb.setB(4);
aa = bb;
If we have 2 classes like this :
public class A {
public static int m=10;
public int b(){ m++; return m;}
public int fun() {
return b();
}
}
public class Testfun() extends A {
#Override
public int b() {return 1;}
public void test(){
A a = new A();
assertEquals(1,a.fun());
}
}
Is there any way to make the method fun() in class A call the overriden b() instead of the its super b()?
The idea is:
I suppose to test the method fun() and do a stub b(). So I don't want the method to call the original b() and call the stub one.
Is there any way to make the method fun() in class A call the overriden b() instead of the its super b() ?
No way. The instance you have is of type A and methods from A gets called. Period.
No you can not call.The instance you have is of type A and methods from A gets called.
No, it's not possible, because object don't know how many of it's childs or are there any of it. When you want to test something inside a class and want to stub it it's signal of you need to make it dependency of the class like this:
public class A {
private final B b;
public A(B b) {
this.b = b;
}
public int fun() {
return b.b();
}
}
public interface B {
int b();
}
public class Testfun() {
public void test(){
B b = new B {
public int b() {
return 1;
}
};
A a = new A(b);
assertEquals(1, a.fun());
}
}
In this example we make B as dependency of class A and able to change B from desirable implementation in runtime to test dummy in testing. When you need to test B itself you need separate class that tests B. See https://en.wikipedia.org/wiki/Strategy_pattern
Thanks for all, it really helped me !
My mistake was here
A a = new A();
It should be :
A a = new Testfun();
Therefor the overriden b() will be called.
Assuming I have a super class that has 3 parameters in it's constructor and i am inheriting this class that also has a constructor with 3 parameters, and I want to call the super class constructor but before I want to do some logic on the sub class first, I can call a static method that receives those 3 parameters but I have to return only one, so this is the solution I came up with
public class someClass extends SuperClass {
public someClass(int a,int b,int c) {
super(func(a,b,c),b,c);
}
public static int func(int a,int b,int c){
//usage a b c
return a;
}
}
It seems a bit ugly and I was wondering if there is a better solution to use the parameters myself and then call super regularly. Note that i cannot change the Super class or that usages of the sub classes and therefore factory Design Pattern
To get the logic out of your constructor, you can easily create a factory method in your subclass:
public class SomeClass extends SuperClass {
private SomeClass(int a, int b, int c) {
super(a, b ,c);
}
public static SomeClass create(int a, int b, int c){
// calculate a for constructor
return new SomeClass(a, b, c);
}
}
Then you can create instances as follows:
SomeClass someClass = SomeClass.create(1, 2, 3);
In Java you are not allowed to execute another statement before the call to super. The trick you mentioned works, but you cannot refactor your code to have the call to func in a statement before the call to super.
In my experience, issues like this often hint at some design issue. Maybe you can solve the underlying problem by re-thinking about the responsibilities of the two involved classes.
You could also use the builder pattern
public class SomeClass extends SuperClass {
public static class Builder {
private int a, b, c;
public Builder withA(int a) {
this.a = a;
return this;
}
public Builder withB(int b) { ... }
public Builder withC(int c) { ... }
public SomeClass build() {
// logic goes here
return new SomeClass(...)
}
}
// hide this from public use, use Builder instead
protected SomeClass(int a, int b, int, c) {
super(a, b, c);
}
}
SomeClass someClass = new SomeClass.Builder().
withA(1).
withB(2).
withC(3).
build();
I have a super class named TestSuper
public class TestSuper {
int a = 0;
}
and I have 2 sub classes named TestSub and TestSub2 that extend TestSuper
public class TestSub extends TestSuper{
int a=1;
}
public class TestSub2 extends TestSuper{
int a=2;
}
in my main class i created a method that takes in a type TestSuper and returns the a value of it and in the main i display it on the console
public class Main {
public static void main(String[] args){
System.out.println(test(new TestSub())+" "+test(new TestSub2()));
}
public static int test(TestSuper b){
return b.a;
}
}
but the output is "0 0" instead of "1 2", what do I do?
You need to cast the reference so say which one you want.
public static int test(TestSuper b){
return b instanceof TestSub ? ((TestSub) b).a :
b instanceof TestSub2 ? ((TestSub2) b).a :
b.a;
}
If this seems needlessly complicated, it is. You should use polymorphism instead.
public class TestSuper {
int a = 0;
public int getA() { return a; }
}
public class TestSub extends TestSuper {
int a = 1;
public int getA() { return a; }
}
public class TestSub2 extends TestSuper {
int a = 2;
public int getA() { return a; }
}
public static int test(TestSuper b) {
return b.getA();
}
First understand the difference between hiding and overriding: https://docs.oracle.com/javase/tutorial/java/IandI/override.html
Then create a getter method in the base-class which you can override in the subclass.
You can look into the theory behind this, and then do the only reasonable thing -forget about writing such kind of code.
In good OOP you consider your fields to be part of your "secret" internal implementation. You don't use fields of sub classes in the super class context. Period.
You are even very conservative about making a field protected in the superclass and to use that in subclasses.
When you call test method like this:
test(new TestSub())+" "+test(new TestSub2())
You use upcasting. Upcasting seperates interface and implementation for an object. But for seperating interface and implementation and achieving true implementation in polymorphism, you must use polymorphic structures. The instance variables aren't polymorphic. Because of this, actually you call a variable which is in TestSuper class.
Only instance methods are polymorphic.
So I have this abstract class
public abstract class A {
protected final boolean b;
protected A (boolean b){
this.b = b;
}
}
And this class that extends A
public class C extends A{
protected C() {
super(false);
}
}
I dont want "b" to be able to change its' value once it's initialized
But I dont know how to do it without the compiler going haywire.
Any suggestions are welcome. Thanks in advance.
EDIT1: static removed from b.
EDIT 2: Ok realised the problem and fixed see above.
Special thanks to J.Lucky :)
I'd suggest you make use of the final keyword.
Try the following codes:
abstract class A {
final protected boolean b;
A(boolean b) {
this.b = b;
}
//No setter method
//public abstract void setB(boolean b);
public abstract boolean getB();
}
class C extends A {
C(boolean b) {
super(b);
}
#Override
public boolean getB() {
return b;
}
}
Sample implementation would be:
public static void main(String args[]) {
C c = new C(true);
System.out.println(c.getB());
}
Since b now is a final variable, you will be forced to initialize it on your constructor and you will not have any way of changing b anymore. Even if you provide a setter method for b, the compiler will stop you.
EDIT 2:
Say you created another class called 'D' and this time you know you want to set it to false by default. You can have something like:
class D extends A {
D() {
super(false);
}
//You can also overload it so that you will have a choice
D(boolean b) {
super(b);
}
#Override
public boolean getB() {
return b;
}
public static void main(String[] args) {
D defaultBVal = D();
D customBVal = D(true);
System.out.println(defaultBVal.getB()); //false
System.out.println(customBVal.getB()); //true
}
}
Solution: You should change the boolean into a Boolean, make it private, provide a getter and a protected setter. In the setter you should check whether the Boolean has been initialized. If so, you should either ignore resetting, or throw and Exception
well how about this:
public abstract class A {
private static Boolean b;
//setB is declared here and, depending on the class that implements it,
//it initializes the value of the variable "b"
protected abstract void setB();
}
public class C extends A{
protected void setB() {
if(b != null) b = true;
}
}
Now the variable is only initialized once when its called. There are still some problems. Someone could use reflection to change the value. Also, when the object is serialized is possible that someone could change the value. If you have a multiple threads accessing this then you should synchronize the method. However, if these aren't issues then this solution might work for you.