public class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.a); //Super-Attribut
System.out.println(s.m1()); //Sub-Attribut
System.out.println(new Sub().m2()); //Super-Attribut
}
}
class Super {
String a = "Super-Attribut";
String m1() {
return a;
}
String x() {
return a;
}
}
class Sub extends Super {
String a = "Sub-Attribut";
String m1() {
return a;
}
String m2() {
return x();
}
}
I have a question regarding the above code, especially the line System.out.println(new Sub().m2()). In this line an instance of the class Sub is created. On this instance the function m2() in the class Sub is called. The method m2() in Sub calls the method x() in Super. The method x() returns the string variable a.
Shouldn't this a be the a, which is declared in the class Sub, since an object of the class Sub is being used, i.e the runtime type is Sub, and also the declaration type or the static type of the used object, which is new Sub(), is Sub?
Related
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 ...
}
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]
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.
public class ExampleClass {
public static void main(String[] args) {
// Upcasting from subclass to super class.
A aRef=new C();
//aRef.setMessage(); compilation Error
aRef.display();
B bRef = (B)aRef;
//bRef.setMessage(); compilation Error
bRef.display();
C cRef = (C)aRef;
cRef.setMessage("ayaz");
cRef.display();
}
}
interface A
{
void display();
}
class B implements A
{
public void display() {
System.out.println("Am in class B");
}
}
class C extends B
{
String msg = "Am in class C";
#Override
public void display() {
System.out.println(msg);
}
public void setMessage(String s){
msg = s;
}
}
In the above code after downcasting aRef object to an object of type B unable to call setMessage(),though on calling display with bRef Obj, display method of C class is called. When we downcast to Obj of C then we are able to call why? is aRef only pointing to an object of type C, I think reference is not copied.
Two things:
at compile time the compiler looks at the type of the reference to determine if the method exists (is at least declared). So aRef.display() is correct as bRef.display() and cRef.display(). But aRef.setMessage() and bRef.setMessage() are incorrect (setMessageis not a method declared or defined in A or B. Of course cRef.setMessage() is correct.
at runtime the machine finds the correct method to execute. As aRef, bRefand cRef refer to the same C object that redefines the method display, this one is called.
Although the Object which resides in the heap is of Class C,the reference you have used is of Type B.You can only call the methods which exist in the reference and not the methods present in the actual Object.
1)Only Class C has setMessage method.So only a reference of Object C can invoke this method.Alternatively you can define these methods in interface and Class B and mark Class B as abstract with a concrete implementation in Class C
public class ExampleClass {
public static void main(String[] args) {
// Upcasting from subclass to super class.
A aRef=new C();
aRef.setMessage(); //No compilation Error now
aRef.display();
B bRef = (B)aRef;
bRef.setMessage(); //No compilation Error now
bRef.display();
C cRef = (C)aRef;
cRef.setMessage("ayaz");
cRef.display();
}
}
interface A
{
void display();
void setMessage(String s);
}
abstract class B implements A
{
public void display() {
System.out.println("Am in class B");
}
}
class C extends B
{
String msg = "Am in class C";
#Override
public void display() {
System.out.println(msg);
}
public void setMessage(String s){
msg = s;
}
}
The simple rule is:
The type of the variable tells what can be done
The type of the object tells how to do it
I have an A interface with a method getT(), abstract B class with method getS() and class C that extends B class which implements A interface. I'm overriding methods from A interface and B superclass inside the C subclass. Then in the main method I instantiate the C class to be typeo if A like this: A obj = new C(); I'am able to call the getT() from obj, but can't call getS() method. How can I call getS() method from obj, but I can't change the type of obj, it has to be A. Here is the code:
Interface A :
public interface A {
public String getT();
}
Abstract class B :
public abstract class B implements A {
public abstract String getS();
}
subclass C :
public class C extends B {
#Override
public String getT() {
System.out.println("method getT() from C class");
return null;
}
#Override
public String getS() {
return null;
}
}
And the main method inside of the T class :
public class T {
public static void main(String[] args) {
A obj = new C();
obj.getT();
}
}
With a reference variable of type A, you cannot call getS(), because it could be any type that implements A, say, AImplementer, that doesn't extend from B. Any A object doesn't necessarily have a getS() method. It's only guaranteed to have a getT() method.
If obj has to be a type A and you need to call getS(), then include the getS() method in the definition of the A interface:
public interface A {
public String getT();
public String getS(); // Add this line.
}
Then B is still an A, and you can call getS() on an A reference variable.
By the way, I don't see any static methods in your code. Static methods cannot be overridden.
To gain access to the method you will need to downcast obj to B.
So you could have:
((B)obj).getS();
Downcasting: http://www.programmerinterview.com/index.php/java-questions/downcasting-in-java/
the type class of obj is A, but A hasn't method getS() so you can't call in the main method.
obj must be class B or class C.