Cannot get value of property from extending class - java

I have two Java classes, one of which inherits from other. They are somewhat like the following:
A.java:
public class A {
public String invocations[] = {"foo"};
public A() {
// do stuff
}
}
B.java:
public class B extends A {
public String invocations = {"bar", "baz"};
public B() {
super();
}
}
In this example, assuming I create an instance of B and get its invocations property, it returns {"foo"} instead of the expected {"bar", "baz"}. Why is this, and how can I get the {"bar", "baz"}?

You have one variable hiding another one. You can refer to a variable in a super class by using a cast to the type explicitly. (I am assuming you fix the syntax errors)
public class Main {
static class A {
public String[] invocations = {"foo"};
}
static class B extends A {
public String[] invocations = {"bar", "baz"};
}
public static void main(String... args) {
B b = new B();
System.out.println("((A)b).invocations=" + Arrays.toString(((A) b).invocations));
System.out.println("b.invocations=" + Arrays.toString(b.invocations));
}
}
prints
((A)b).invocations=[foo]
b.invocations=[bar, baz]

Related

Modifiy method called from extended class

I have three classes, and I need to modify first class through the second that is extended :
my first class A :
public class A{
private String name;
public void setName(String name) {
this.name= name;
}
my second class B
public abstract class B {
public void init() {
A a = new A();
a.setHost("foo");
}
}
my third class C
public class C extends B {
// I want to use the method setName() of the a declared in class B
b.init.a.setName("bar");//compile error, I tried several syntax I don't know how to do it
}
expected output, in my third class :
a.Getname = "bar"
Your code has multiple issues:
1) Variable b is never declared.
2) Variable a is private to method init, so you can't access it outside the init method.
So the solution should be like:
Class B:
public abstract class B {
protected static A a = new A(); // Protected to make it visible to child class
public void init() {
a.setHost("foo");
}
}
Class C:
public class C extends B {
public static void main(String[] args) {
a.setName("bar");
System.out.println(a.getName()); //Output = bar
}
}
you can return a in the init method of B like below.
public A init() {
A a = new A();
a.setHost("foo");
return a;
}
Then you can set the value in C like below
public class C extends B {
public setNameinA() {
B b = new B();
b.init().setName("bar");
}
}

Call base method on generic object of derived class

Trying to add a base interface with method so all derived classes have to implement the method or use default method. What's the best way to going about getting this method callable? See comment in code block below.
public interface IA{}
public interface IB{
public Integer doWork();
}
public interface IC extends IB{
}
class B implements IB{
Integer doWork(){
return 2;
}
}
class C extends B implements IC{
#Override
Integer doWork(){
return 7;
}
}
//What do I need to do to cast clazz to an object so I can call the derived class' doWork method?
private Integer newClient(Class<T> clazz){
((B) clazz).doWork();
}
Ended up finding a solution:
B.class.cast(clazz);
As for how to ensure you call the derived class' method that overrides the base, that is a native behavior of Java.
Example Program:
public class Foo {
static class A {
int get() { return 0; }
}
static class B extends A {
#Override
int get() { return 1; }
}
public static void main(final String[] args)
{
A a = new A();
B b1 = new B();
A b2 = new B();
printA(a);
printA(b1);
printA(b2);
}
public static <T extends A> void printA(T bObj) {
System.out.println(bObj.get());
}
}
Output:
0
1
1
Note that the output returned from b2::get()::int is the same as b1::get()::int, even though b2 is type A and b1 is type B. This is because even though we only have a reference to the A class in b2, the object implementation is still B.
It seems that you only want to know how to instantiate the Class. Assuming it has a default constructor you can do it this way:
private Integer newClient(Class<B> clazz){
try {
((B) (clazz.getConstructor().newInstance())).doWork();
} catch ...
}

About Method Overloading in Java

Can method overloading take place only within the same class? Or can it take place within sub classes?
There is no restriction on overloading within sub-classes. For example, I could have:
public class A {
public String test(String input) {
//do something
}
}
public class B extends A {
public String test(String input, String input2) {
//do something
}
}
B testInstance = new B();
testInstance.test("one", "two");
testInstance.test("one");
For questions like this, you can always try it yourself and find out.
In a word - yes. You can overload methods in a subclass. E.g.:
public class Parent {
public void print(String s) {
System.out.println("That was a string: " + s);
}
}
public class Child extends Parent{
public void print(int i) {
System.out.println("That was an int: " + i);
}
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
c.print("hello"); // prints "That was a string: hello"
c.print(7); // prints "That was an int: 7"
}
}
When you overload a method, it's basically creating an entirely new method with no direct association with the other of the same name, it's the signature that matters.
so if you make a method in the subclass that has different signature it will be treated as different and new method for that class by the compiler so it won't be relating it to the method of super class.
Overloading can be possible in sub classes. If you create a method with the same name as in super class with different parameter then it will be treated as separate method. Sub class will have methods from super class as well so which method to be called is decided at compile time based on the parameter type. Which method to be called is declared at compile time that is why it's called static polymorphism. Here is the example -
Class A{
void m1(int x){
System.out.println("m1 in A");
}
}
Class B extends A
{
void m1(String str)
{
System.out.println("m1 in B");
}
}
Public Class Test
{
public static void main(String[] aa)
{
B b = new B();
b.m1(10);
b.m1("Hello World!!")
}
}
Hope this will help.

Can a superclass type variable refer to a subclass object?

For example:
public class A {
public class B extends A {
}
public static void main(String[] args) {
A a;
a = new B();
}
}
I searched some similar questions and they showed "yes, a superclass type variable can refer to a subclass object". But in eclipse the above code comes up with an error like "No enclosing instance of type A is accessible. Must qualify the allocation with an enclosing instance of type A (e.g. x.new A() where x is an instance of A)."
So what wrong? Thanks!
The answer is "yes" superclass can refer to a subclass, but you're asking the wrong question.
You're getting this error because B is an enclosed class of A (meaning you must have an instance of A to have an instance of B), but you're referring to it from a static method (ie not an instance of A).
Simply change B to be a static class.
public class A {
public static class B extends A { // <-- Added static keyword
}
public static void main(String[] args) {
A a;
a = new B();
}
}
No errors.
The other option is leave it an enclosed class and do this:
public class A {
public class B extends A { // leave B as an enclosed class
}
public static void main(String[] args) {
A a = new A();
a = a.new B(); // can only create a B in the context of an A
}
}
check your parantheses!! It should be:
class A {
}
public class B extends A {
public static void main(String[] args) {
A a;
a = new B();
}
}
Also you have two public classes in your code!!

Java: static field in abstract class

I just start out with an example, that explains it best:
public abstract class A{
static String str;
}
public class B extends A{
public B(){
str = "123";
}
}
public class C extends A{
public C(){
str = "abc";
}
}
public class Main{
public static void main(String[] args){
A b = new B();
A c = new C();
System.out.println("b.str = " + b.str);
System.out.println("c.str = " + c.str);
}
}
This will print out:
b.str = abc
c.str = abc
But I would like a solution where each subclass that instantiate the super class, has their own class variable, at the same time I want to be able to reference that class variable through the identifier, or a method call, defined in the abstract super class.
So I would like the output to be:
b.str = 123
c.str = abc
Is that doable?
If you want classes B and C to have separate static variables, you'll need to declare the variables in those classes. Basically, static members and polymorphism don't go together.
Note that accessing static members through references is a really bad idea in terms of readability - it makes it look like it depends on the value of the reference, when it doesn't really. So your current code won't even compile when you've moved str down to B and C. Instead, you'll need
System.out.println("b.str = " + B.str);
System.out.println("c.str = " + C.str);
If you really need to access the value polymorphically (i.e. through an instance of A) then one option is to make a polymorphic getter:
public class A {
public abstract String getStr();
}
public class B extends A {
private static String str = "b";
#Override public String getStr() {
return str;
}
}
(and the same for C).
That way you get the behaviour you want in terms of not having a separate variable per instance, but you can still use it polymorphically. It's a little odd for an instance member to return a static value like this, but you're using the value for polymorphism of type, basically...
public abstract class A {
private String str;
public String getStr() { return str;}
protected void setStr(String str) { this.str = str; }
}
Then you'll be able to have
B b = new B();
b.getStr();
The setter and getter are my addition, you can go by simply making the variable non-static.
Update If you want to have the static-per-subclass, then you can have:
protected static Map<Class, String> values;
public abstract String getValue();
and then:
public String getValue() {
values.get(getClass());
}
public void setValue(String value) {
values.set(getClass(), value);
}
But this is generally a bad idea.
Put the static varibale in each subclass and add a (not static) abstract method to the abstract superclass:
abstract String getStr();
Then implement the getStr() method in each subclass by returning the static field of this special subclass.
public class B extends A {
private static String str;
#Override
public String getStr() {
return B.str;
}
}
only one instance of static variable is present in the system.
static variable will load into the system in the start before class is loaded.
reason both time abc is printed is because you set the value of str as abc in the last.
This will print the output you want:
public abstract class A{
}
public class B extends A{
static String str;
public B(){
str = "123";
}
}
public class C extends A{
static String str;
public C(){
str = "abc";
}
}
public class Main{
public static void main(String[] args){
A a = new B();
A c = new C();
System.out.println("B.str = " + B.str);
System.out.println("C.str = " + C.str);
}
}
Since you hardcode the value or str in subclasses anyway, you can do something like this:
public abstract class A{
public abstract String getStr();
}
public class B extends A{
public String getStr(){
return "123";
}
}
public class C extends A{
public String getStr(){
return "abc";
}
}
This would do the trick in your case.
Of course, then you should call it by method, like this:
public class Main{
public static void main(String[] args){
A b = new B();
A c = new C();
System.out.println("b.str = " + b.getStr());
System.out.println("c.str = " + c.getStr());
}
}
It is what I did to avoid to have to implement the same method in every subclass. It is based on the answer of Bozho. Maybe it may help someone.
import java.util.HashMap;
import java.util.Map;
/**
*
* #author Uglylab
*/
public class SandBox {
public static void main(String[] args) {
A b = new B();
A c = new C();
System.out.println("b.str = " + B.getStr(b.getClass()));
System.out.println("c.str = " + C.getStr(c.getClass()));
}
}
abstract class A{
protected static Map<Class, String> values = new HashMap<>();
public static String getStr(Class<? extends A> aClass) {
return values.get(aClass);
}
public static void setStr(Class<? extends A> aClass, String s) {
values.put(aClass, s);
}
}
class B extends A{
public B(){
setStr(this.getClass(),"123");
}
}
class C extends A{
public C(){
setStr(this.getClass(),"abc");
}
}
I think one way to approach this is to use a singleton for class B and C to mimic static methods and fields. The can both extend abstract class A, but will have their own values of str..

Categories