Java ArrayList call extended object function - java

I have a ArrayList<A> and am putting "B" objects into it. In the code for "B" I am overriding the print function. However, in my code I end up getting the print function defined in "A" instead.
I was wondering if there was a way to get the "B" print function without using a if statement checking if "A" is a "instanceof" "B", if true then casting "A" to "B", then calling print. Let's also say I can't make the class abstract and can't make print abstract.
Here is my code to show what I mean:
Class A
public class A {
public String print() {
System.out.print("A");
}
}
Class B
public class B extends A {
public String print() {
System.out.print("B");
}
}
Main:
ArrayList<A> objects = new ArrayList();
objects.add(new B());
Class a = objects.get(0);
a.print();
Output = "A"
So this will print "A". Again, I know I can use a if statement check if it's from the "B" class then cast type to object to it. But let's say I am going to put the whole alphabet into it and I don't want an if and a bunch of else if statements? Is that the only way?

This seems to work for me.
public class testing{
private static class A{
public void print(){
System.out.println("A");
}
}
private static class B extends A{
#Override
public void print(){
System.out.println("B");
}
}
public static void main(String[] args) {
ArrayList<A> objects = new ArrayList<A>();
objects.add(new B());
A a = objects.get(0);
a.print();
}
}
upon looking at your code, the print functions should return void not String, or better yet they should actually return a String instead of printing within the method (wither way this fixes compile errors).
You are missing the type argument when your create your objects ArrayList (seem my example).
Its better practice to add the #Override annotation to tell the compiler that you are in fact overriding a method (see example)
Lastly you cannot declare an instance of A the way you have (Class a = objects.get(0);) you need to actually declare it as type A or B (again see my example)

Related

What happend will subClass and SuperClass have same attributes in Java?

public class Test {
public static void main(String[] args) {
B b = new B();
b.test();
}
}
class A {
String aString = "a";
void test() {
System.out.println(aString);
}
}
class B extends A {
String aString = "b";
}
why the cant input out "b"?
i just think b.test() will call method of superClass, so b will user superClass's attribute.
why the cant input out "b"? i just think b.test() will call method of superClass, so b will user superClass's attribute.
Java class and instance variables can be inherited, but they are not virtual. That is, all variable identifiers appearing in Java code are resolved at compile time -- there is no dynamic resolution for them.
Thus, the appearance of identifier aString in method A.test() is resolved at compile time to the aString attribute of class A. This is the attribute that all invocations of that method will access, regardless of the actual class of the object on which it is invoked. If you want to use the attribute of class B when test() is invoked on an instance of that class then provide getter methods in classes A and B and have A.test() obtain the string via those.
The variable in b is hiding the variable in a. You can fix it by removing the type in b
class B extends A {
public B () {
aString = "b";
}
}
class A {
String aString = "a";
void test() {
System.out.println(aString);
}
}
class B extends A {
String aString = "b";
}
Creates 2 aString variables for B. While A will not know about B extending it, B can always access "things" from its parent class A, using the super keyword. So when you are in B, you can use aString and super.aString and they will refer the 2 different variables:
class Ideone {
public static void main (String[] args) {
A a=new A();
B b=new B();
a.test();
b.test();
b.suptest();
}
static class A {
String aString="A.aString set from A";
void test() {
System.out.println("A.test(): "+aString);
}
}
static class B extends A {
String aString="B.aString set from B";
{
super.aString="A.aString set from B";
}
void test() {
System.out.println("B.test(): "+aString);
}
void suptest() {
System.out.print("B.suptest() calling super.test(): ");
super.test();
}
}
}
You can try it on IdeOne, produces output
A.test(): A.aString set from A
B.test(): B.aString set from B
B.suptest() calling super.test(): A.test(): A.aString set from B
Where the first two lines show nothing fancy, A.aString and B.aString both contain their initial value.
But the third output line shows that super.test() call in B really "ends" in A.test(), and that the initializer block in B really altered the inherited aString field.
(Side note: the static class magic relates to the example being contained in a single file, it doesn't affect the inheritance-part)
You are correct.
Since Class A and the method test() are not abstract and the fact that the method test() was not overrided by its subClass B, the return will be exactly how was specified in Class A even if you call it from a B instance.

When does the constructor initiallize?

I wrote down this mini-program:
A class:
public class A
{
public A()
{
System.out.println(getS());
}
public String getS() { return s;}
}
B class:
public class B extends A
{
private String s = "hello2";
public String getS() { return s;}
}
main:
public static void main(String[] args)
{
B b = new B();
}
and it printed:
null
Why is that?
I know that the String that printed is B's string, but why it didn't initialized before?
According to this answer - the variable initialized before the constructor..
EDIT -
I edited the code so the unrelated code won't confuse
Here is what's going on: when you construct B, the first thing its constructor needs to do is constructing A. This is done before B's own field s is initialized.
A constructs its own s, and then calls getS. However, it does not get its own getS, because B provides an override for it. Recall that B.s has not been initialized yet. That is why you see null printed.
Follow-up reading: What's wrong with overridable method calls in constructors?
What is happening:
You create a B instance, this will call the super() so the constructor of A.
Here it will do the print using the getter getS(). This will use the getter of B since this is the type of this but in this getter, the String is not yet instanciate since it is still doing the super class construction, so it return null.
Note that the String s in A is hidden by the one in B
The order during an instance is :
the static (from the super then the class)
the super class declaration (statement then constructor)
the block statement
the constructor
As Seen with :
public class A{
static{System.out.println("sA");}
{System.out.println("A1");}
public Main() {
System.out.println("new A");
}
{System.out.println("A2");}
public static void main(String[] args) {
new A();
}
}
class B extends Main {
static{System.out.println("sB");}
{ System.out.println("B1"); }
public B() {
System.out.println("new B");
}
{ System.out.println("B2"); }
}
Output :
sA
sB
A1
A2
new A
B1
B2
new B
it prints null because you have polymorphism in java. You Overrided method getS(). So when you call it from A, you try to call getS() from class B. But you didn't create instance of class B yet, because you need to finish class A first. So String in class B haven't been initialized yet, because of it you get null.

I've got trouble with inner and static inner class at java

Firstly, Thanks everybody that read that topic.
How can if statement become true in test class? I couldnt find any solution.I couldnt write any code in these method.I tried to send from Room class numberOfTiger to class Question's method but I didnt achieve that.
That's question about ,How can I change int variable(numberofTiger) to Cat.Tiger variable.After that if statement become true to invoke (getNumberOfTiger) method.
public class Test {
public static void main(String[] args) {
Animal an = new Animal();
Animal.Cat an1 = an.new Cat();
Animal.Cat.Tiger an2 = an1.new Tiger(3, 900, 2);
if (Animal.Question.getnumberOfTiger(an2) == 3) {
System.out.println("True");
}
}
}
public class Animal {
Cat[] c;
// inner class
class Cat {
Tiger[] t;
// inner class
class Tiger {
private int numberOfTiger;
private int averageOfTigerWeigth;
private int youngTiger;
public Tiger(int numberOfTiger, int averageOfTigerWeigth, int youngTiger) {
super();
this.numberOfTiger = numberOfTiger;
this.averageOfTigerWeigth = averageOfTigerWeigth;
this.youngTiger = youngTiger;
}
static class Question {
static int getnumberOfTiger(Cat.Tiger a) {
return 0;
}
}
}
In addition to either making Cat a static class, or using its instance,
you also need a getter for a.numberOfTiger since it is private, in Tiger class:
public getNumberOfTiger() {
return numberOfTiger;
}
Then:
return a.getNumberOfTiger();
In getNumberOfTiger() you need to return the number of tigers associated with that object. You are currently just returning 0, so it will always evaluate to false.
I see the issue. The Tiger class and the Cat class needs to be static. The reason is, a non-static inner class can call on its outer class (e.g. Cat.this.something). A non-static inner type is called like this:
instanceOfOuterClass.innerClass
whereas a static inner type is called like this:
outerClassName.innerClass
The simplest way to call on a non-static inner type is new Outer().new Inner(); The main issue with beginners in Java is that they try to do this:
new (new Outer()).Inner()
But the actual way to call it is
new Outer().new Inner()
Also, your method is always returning 0 for the count of tigers.

Parent NoArgument Contructor invoking overridden method

ot sure if a similar question do exists or have been answered earlier. I did a search but couldn't find anything related.
Please see following example. There's a class A with noargument contructor. Class B extends Class A but no default contructor exists. The output is B-> get c, and I think java uses the runtime polymorphism logic to invoke the B object method.
Here would like to understand if its correct and how Java works here (Maybe what's the underlying logic)
Thanks
public class A {
private String cStr="";
private String dStr="";
A()
{
getcStr();
}
public String getcStr() {
System.out.println("A-> get c");
return cStr;
}
public String getdStr() {
System.out.println("A-> get d");
getcStr();
return dStr;
}
}
public class B extends A{
private String cStr;
public String getcStr() {
System.out.println("B-> get c");
return cStr;
}
}
public static void main (String[] args)
{
A a= new B();
a.getdStr();
}
EDIT: the output for the a.getdStr() is A-> get d B-> get c
If a class doesn't have a default constructor, in your case B, then java will implicitly insert a no argument constructor something like this
public B() {
super();
}
To answer your question, Yes, due to run time polymorphism, Java invoke's B's getcStr() method. Because B's constructor is calling A's constructor via super()
This is a famous anti-pattern. And its anti-pattern because you are trying to invoke a overriden method on B before B is fully constructed
Imagine your B class was like this
public class B extends A{
private String cStr = "abc";
public String getcStr() {
System.out.println(cStr);
return cStr;
}
}
Now the output of your program would have been null instead of "abc" because B is not fully constructed yet (that means cStr is not initialized to "abc")
there is no default constructor for B so it'll call A() constructor.....
Now new B(); creates the object of B so java will first look into class B that is any procedure like getcstr() exists if procedure found there it will invoke it otherwise check in the super class for that procedure......

Calling An Inherited Class Method From Java

In Python, class methods can be inherited. e.g.
>>> class A:
... #classmethod
... def main(cls):
... return cls()
...
>>> class B(A): pass
...
>>> b=B.main()
>>> b
<__main__.B instance at 0x00A6FA58>
How would you do the equivalent in Java? I currently have:
public class A{
public void show(){
System.out.println("A");
}
public void run(){
show();
}
public static void main( String[] arg ) {
new A().run();
}
}
public class B extends A{
#Override
public void show(){
System.out.println("B");
}
}
I'd like to call B.main() and have it print "B", but clearly it will print "A" instead, since "new A()" is hardcoded.
How would you change "new A()" so that it's parameterized to use the class it's in when called, and not the hard-coded class A?
Static methods in java are not classmethods they are staticmethods. In general it is not possible to know which class reference the static method was called from.
Your class B does not have a main method and static methods are not inherited.
The only way I can see this happening is to find whatever is calling A.main( String[] arg ) and change it to call B.main instead.
B.main:
public static void main( String[] arg ) {
new B().run();
}
How is your program started? Is there a batch file, shortcut, etc? Something you can change? Where does A.main get called?
I think this isn't possible. Here's why:
In Java, the implementation of a method is determined by the instance's run-time type. So, to execute B.show(), you need to have an instance of B. The only way I could see to do this, if the method that constructs the instance is supposed to be inherited, is to use Class.newInstance() to construct an instance of a type that's not known at runtime.
The problem with that is that within a static method, you have no reference to the containing class, so you don't know whose newInstance method to call.
Why do you want to do this, though? There may be some better way to achieve whatever it is you want to achieve.
In your example I wouldn't put your main method inside of A. This is setup as the entry point into the system (you can't be in B if you are specifically entering into A).
In the example below I created class A, B, and C. Class C instantiates A and B and runs them. Notice that in C I created an A, a B, and another A that I instantiate as a B. My output is:
A
B
B
Hopefully this makes sense.
public class A {
public void show(){
System.out.println("A");
}
public void run(){
show();
}
}
public class B extends A {
#Override
public void show(){
System.out.println("B");
}
}
public class C {
public static void main(String[] args) {
A a = new A();
B b = new B();
A anothera = new B();
a.show();
b.show();
anothera.show();
}
}

Categories