Simulate constructor overriding in Java? - java

Several times I thought it will be good to have overridable constructor in Java.
"Overridable" means the logic of construction can be overriden and/or extended in descending classes in the same way it is possible to override normal methods, i.e. with ability to call parent method AFTER the child.
This task can be formulated as to have a method, say, called init() which is called at construction time, but only in the last constructor of the stack.
Like:
public class InitializationOverride {
public static class A {
A() {
System.out.println("Constructor of A");
}
void init() {
System.out.println("Init of A");
}
}
public static class B extends A {
B() {
System.out.println("Constructor of B");
}
#Override
void init() {
System.out.println("Init of B");
}
}
public static class C extends B {
C() {
System.out.println("Constructor of C");
}
#Override
void init() {
System.out.println("Init of C");
}
}
public static void main(String[] args) {
new A(); // should print "Constructor of A, Init of A"
new B(); // should print "Constructor of A, Constructor of B, Init of B"
new C(); // should print "Constructor of A, Constructor of B, Constructor of C, Init of C"
}
}
The obvious way is to write
public static void main(String[] args) {
new A().init();
new B().init();
new C().init();
}
but this doesn't guarantee init() is not forgotten to call.
Is it possible to do somehow?
UPDATE
It is not known at design time, which class will be "last". It is expected, that class tree will be developed in future.
UPDATE 2
Here is the solution with reflection and constructor code requirement to call currentStage() at the end:
public class InitializationOverride {
public static class A {
A() {
System.out.println("Constructor of A");
currentStage(A.class);
}
void currentStage(Class<?> cls) {
if( cls == getClass() ) {
init();
}
}
void init() {
System.out.println("Init of A");
}
}
public static class B extends A {
B() {
System.out.println("Constructor of B");
currentStage(B.class);
}
#Override
void init() {
System.out.println("Init of B");
}
}
public static class C extends B {
C() {
System.out.println("Constructor of C");
currentStage(C.class);
}
#Override
void init() {
System.out.println("Init of C");
}
}
public static void main(String[] args) {
new A(); // should print "Constructor of A, Init of A"
new B(); // should print "Constructor of A, Constructor of B, Init of B"
new C(); // should print "Constructor of A, Constructor of B, Constructor of C, Init of C"
}
Is it possible to write simpler?

Constructors shouldn't call overridable methods. If invoking of such method is necessary the better solution is makes constructors protected and provide static factory methods:
public class InitializationOverride {
public static class A {
protected A() {
System.out.println("Constructor of A");
}
public static A newInstance(){
A a = new A();
a.init();
return a;
}
protected void init() {
System.out.println("Init of A");
}
}
public static class B extends A {
protected B() {
System.out.println("Constructor of B");
}
public static B newInstance(){
B b = new B();
b.init();
return b;
}
#Override
protected void init() {
System.out.println("Init of B");
}
}
public static class C extends B {
protected C() {
System.out.println("Constructor of C");
}
public static C newInstance(){
C c = new C();
c.init();
return c;
}
#Override
protected void init() {
System.out.println("Init of C");
}
}
public static void main(String[] args) {
A.newInstance(); // should print "Constructor of A, Init of A"
B.newInstance(); // should print "Constructor of A, Constructor of B, Init of B"
C.newInstance(); // should print "Constructor of A, Constructor of B, Constructor of C, Init of C"
}
}
Edit
More explanation: Such solution provide benefits but also drawbacks. You should to provide a contract for classes (i.e. in Javadoc) that sub-classes that extends your class should follow this standard of objects creation. Also it creates more code. The profit is that objects created in that way:
C obj = C.newInstance()
...are always fully initialized and there is no need to remember for call init() method explicite.
Remember that it also will be the only method for create object outside the class' package (constructor won't be available), but inside same package constructor will be still available (protected methods are available inside same package)

In Java, when child class is instantiated, default constructor of parent class is always invoked (unless any other constructor is specified). Now, if you need to have a common code that needs to be executed for all the classes, it's recommended to put it in constructor. However, if you want something to be executed only in the last class in the hierarchy then (a) you can write it into the last constructor itself or (b) write an initialisation block, below example demonstrates this:
public class Test extends Test2{
public Test(){
System.out.println("In test");
System.out.println("Init last");
}
{
System.out.println("Init");
}
public static void main(String[] args) {
new Test();
}
}
class Test2{
public Test2(){
System.out.println("In test 2");
}
}

Just change your a class constructor like this, each object init method will call by calling this.init(), you required to change just most upper class constructor.Because at time of object creation parent class constructor will definitely call
public class Test {
public static class A {
public A() {
this.init();
}
void init() {
System.out.println("Called in A");
}
}
public static class B extends A {
#Override
void init() {
System.out.println("Called in B");
}
}
public static class C extends B {
#Override
void init() {
System.out.println("Called in C");
}
}
public static void main(String[] args) {
new A(); // should "Called in A" printed
new B(); // should "Called in B" printed
new C(); // should "Called in C" printed
}
}

Use super.init() for this to call root parent class init() .

Related

super not working as I expected? (calling derived method instead of base method)

Let's say we have the following code:
public class A {
void someMethod() {
System.out.println("Some method from A");
}
void someOtherMethod() {
System.out.println("Some other method from A");
this.someMethod();
}
}
public class B extends A {
void someMethod() {
System.out.println("Some method from B");
}
void test() {
System.out.println("Test method from B");
super.someOtherMethod();
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.test();
}
}
The output is:
Test method from B
Some other method from A
Some method from B
Why in 'someOtherMethod()' from A, when we call 'this.someMethod()' the program calls the method from B. I was expecting it to call 'someMethod()' from A and print 'Some method from A' on the third line instead of 'Some method from B'. Why is this happening and how can I make it so it works as I intended?

What does makes those methods calls returns those values?

I need to write what is the output of those methods calls.
My answer was:
I i = new A();
i.m(b);
My answer: m_IB because I doesn't have any method with a B type so I went down to class A which implements I. A doesn't also have any methods with parameter B but it extends I.IImpl which has a method with m(B b) that prints m_IB.
I j = new B();
j.m(b);
My answer: m_BB becuase again I doesn't have any method with a B type so I went down to class B because I j = new B() and it has a m(B b) which print m_BB.
interface I {
public void m(A a);
class IImpl {
public static void m(B b) { System.out.println("m_IB"); }
}
}
class A extends I.IImpl implements I {
public void m(A a) { System.out.println("m_AA"); }
}
class B extends A {
public void m(A a) {
super.m(a);
System.out.println("m_BA");
}
public static void m(B b) { System.out.println("m_BB"); }
}
public class Interfac {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.m(b); System.out.println(); // m_IB
I i = new A();
i.m(b); System.out.println(); // m_AA
I j = new B();j.m(b); // m_AA m_BA
}
}
Both of my answers are wrong and the correct output is m_AA for i and m_AA m_BA for j.
I can't understand why I get this output even if I'm calling a method with a type B.
Both of the correct answer are calling a m(A a) methods.
Your interface provides this method:
public void m(A a);
And your j is declared like this:
I j = new B();
So, yes, it's an instance of B, but it is declared as an I, meaning, when you call that method, it calls the method provided by the interface, not the overloaded one.
So, in class B it takes the method that is provided by the interface:
public void m(A a) { // this one
super.m(a);
System.out.println("m_BA");
}
// not this overloaded one
public static void m(B b) { System.out.println("m_BB"); }
The first line of that method is:
super.m(a);
Which calls the m(a) method in the A class, which then prints: "m_AA".
Then, it prints "m_BA"

Is there a way to access an anonymous class inside another anonymous class?

interface A {
void show();
}
public class Static {
public static void main(String args[]) {
A a = new A(){
public void show(){
System.out.println("In anonymous Class");
A b =new A(){
public void show(){
System.out.println("In nested Anonymous Class");
}
};
}
};
//a.show();
}
}
If I want the to print "In nested Anonymous Class", what should I use instead of a.show()?
//EDITED LATER
Thanks guys But unfortunately mis-typed the code....I didn't mean anonymous class inside a method...but inside the class itself. Sorry for the mistake. Here is the corrected code
interface A {
void show();
}
public class Static {
public static void main(String args[]) {
A a = new A() {
public void show() {
System.out.println("In anonymous Class");
};
A b = new A() {
public void show() {
System.out.println("In nested Anonymous Class");
}
};
};
a.show();
}
}
Normally, it's not possible, since A is an interface and interfaces don't have fields. However, it is possible to access this field using reflection. It is a bit of hack though and I wouldn't suggest using this in the "real world"!
interface A {
void show();
}
public class Static {
public static void main(String args[]) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException {
A a = new A() {
public void show() {
System.out.println("In anonymous Class");
};
public A b = new A() {
public void show() {
System.out.println("In nested Anonymous Class");
}
};
};
// Get the anonymous Class object
Class<? extends A> anonymousClass = a.getClass();
// Get field "b"
Field fieldB = anonymousClass.getField("b");
// Get the value of b in instance a and cast it to A
A b = (A) fieldB.get(a);
// Show!
b.show();
}
}
Note: a better way might be to simply declare a getter on your interface for variable b.
make a call to b.show(); just after class declaration.
A b =new A(){
public void show(){
System.out.println("In nested Anonymous Class");
}
};
b.show();
There is nothing you should use instead of a.show(). That line should be where you put it, and uncommented. Additionally you need b.show() inside:
public static void main(String args[]) {
A a = new A(){
public void show(){
System.out.println("In anonymous Class");
A b =new A(){
public void show(){
System.out.println("In nested Anonymous Class");
}
};
b.show();
}
};
a.show();
}

Java error: class, interface, or enum expected

I need to know the output of this code. But it's not working. Maybe the code is wrong.
I'm still learning how to use Java, and I tried fixing this for hours but still no luck.
Here is the code:
public class A
{
public A()
{
System.out.println ("A");
}
}
public class B extends A
{
public B()
{
System.out.println ("B");
}
}
public class C extends B
{
public C()
{
System.out.println ("C");
}
}
public static void main(String args[]) {
A a = new A();
B b = new B();
C c = new C();
}
Can anyone tell me what is wrong or missing in the code?
Put your main method in a class.
Filename : DemoClass.java
class A
{
public A()
{
System.out.println ("A");
}
}
class B extends A
{
public B()
{
System.out.println ("B");
}
}
class C extends B
{
public C()
{
System.out.println ("C");
}
}
public class DemoClass {
public static void main(String args[]) {
A a = new A();
B b = new B();
C c = new C();
}
}
Another point here is, you can have only public class in a file, so your A B and C all class can't be public in same java file.
Your java file name must be same as public class name. i.e. here DemoClass is public class so file name will be DemoClass.java
Java doc for getting started : getting started with java
For example:
public class Example {
public static void main(String...args) {
new C();
}
public static class A {
public A() {
System.out.println("A");
}
}
public static class B extends A {
public B() {
System.out.println("B");
}
}
public static class C extends B {
public C() {
System.out.println("C");
}
}
}
Also note that this might not print what you would expect. It would actually print:
A
B
C
Why? Constructors are always chained to the super class.
You can, but it is not recommended, nest your classes in a file. It is perfectly valid.
Notice in the output below that each successive child calls its parent's default constructor (super()) implicitly.
I recommend you create the files: A.java, B.java, C.java, and InheritenceTest.java.
public class InheritenceTest {
public class A {
public A() {
System.out.println("A");
}
}
public class B extends A {
public B() {
System.out.println("B");
}
}
public class C extends B {
public C() {
System.out.println("C");
}
}
public static void main(String args[]) {
InheritenceTest i = new InheritenceTest();
A a = i.new A();
B b = i.new B();
C c = i.new C();
}
}
Output:
A
A
B
A
B
C
Warning:
You shouldn't have more than 1 public classes in 1 java file, not recommended. However, it could still work if you didn't use the 'public' identifier (or by using static or inside another class). But for a starter, I would recommend you to have them all in separate files.
Error:
Your main method does not belong to any class. I propose you create another class that includes the public static void main method to test your application.
Info: keep a look at inheritance as your printings might not be what you expect. (Constructor of class B calls the constructor of A, and constructor of class C calls the constructor B which in turn calls the constructor of A).
That's why you get
A
A
B
A
B
C
*due to A() it prints A, then due to B() it prints A B and finally due to C() it prints A B C.
In your case, I would try the following:
//Filename: A.java
public class A {
public A() {
System.out.println ("A");
}
}
//Filename: B.java
public class B extends A {
public B() {
System.out.println ("B");
}
}
//Filename: C.java
public class C extends B {
public C() {
System.out.println ("C");
}
}
//Filename: Test.java
//use a Test class for testing
public class Test {
public static void main(String args[]) {
A a = new A();
B b = new B();
C c = new C();
}
}

Calling a method of a class using an argument of a method which is an object of that class

Consider the following classes
Class A{
public void m1(){
System.out.println("test in A.m1()");
}
public void m2(){
//do something a
}
}
Class B{
public void m1(){
//do something b
}
public void m2(){
//do something b
}
}
Class C{
public void m1(){
//do something c
}
public void m2(){
//do something c
}
}
Class T{
public void m3(Object obj1){
obj1.m1();
}
public void m4(Object obj1){
A a=new A();
m3(a);
}
}
So now my question is, is there any way I can send an open object to a method which will detect what type of object it is and call method of that object class. In this example I am hoping to see the output: "test in A.m1()"
You can use Java's Reflection API to query an arbitrary object to see if it has a method named m1 or m2 and then invoke it. But that is pretty ugly.
Is there anything from stopping you using an interface? Example below (where "..." indicates places where you would put your specific implementation):
interface MyMethods {
public void m1();
public void m2();
}
class A implements MyMethods {
public void m1() { ... }
public void m2() { ... }
}
class B implements MyMethods {
...
}
class C implements MyMethods {
...
}
class T {
public void m3(MyMethods obj1) {
obj1.m1();
}
public void m4(Object obj1) {
// Call m3 three times with different object instance types...
A a = new A();
m3(a);
B b = new B();
m3(b);
C c = new C();
m3(c);
}
}

Categories

Resources