Dependency injection and Inheritance in Java - java

I have the following code:
public class GrandParent {
public void greet() {
System.out.println("Hello from grandpa.");
}
}
public class Parent extends GrandParent {
public void run() {
greet();
}
}
public class RunMe {
public static void main(String args[]) {
Parent p = new Parent();
p.run();
}
public void greet() {
System.out.println("Hi.");
}
}
I am tasked to write the class RunMe and as much as possible, I am not allowed to modify classes Parent and GrandParent. How can I implement this in such a way that when execution reaches run() of Parent, the greet() of RunMe (or it could be in another place) is executed and not the greet() of GrandParent.
Or is this possible in the first place?

I don't see how this is possible if you are to have a non-extended Parent object call a different greet method without changing Parent or Grandparent code.

You could write an instance (not static) inner class within RunMe that extends Parent and overrides Parent instance's run() such that it makes a call to the RunMe instance's run(). Your main() method would create an instance of the new subclass instead of Parent.

First, you need an instance of RunMe to invoke its run() method, since that isn't a static method. One way to hook into what's happening in Parent is to subclass Parent:
public static void main(String args[]) {
final RunMe runMe = new RunMe();
Parent p = new Parent() {
public void run() {
super.run(); // runs Parent.run()
runMe.run(); // runs the hook function
}
};
p.run();
}
I have no idea if this is what you're after.

try this:
public class MyParent extends Parent {
#Override
public void greet() {
System.out.println("hello from MyParent");
}
}
public class RunMe {
public static void main(String args[]) {
Parent p = new MyParent();
p.run();
}
}

I think you meant this:
public class RunMe extends Parent {
public static void main(String args[]) {
Parent p = new RunMe();
p.run();
}
public void greet() {
System.out.println("Hi.");
}
}

Related

How to access overridden method of parent class without using super()?

As shown below, I tried to cast the object of the sub-class to that of its parent class. That went well. But, when I try to access the overridden method of the parent class, it doesn't happen. Instead the overriding method in the child class is called. I know I can do this using the super keyword, but I just want to know why this can't be done by casting?
This is the parent class:
public class Parent {
public void print() {
System.out.println("In parent");
}
}
This is the child class which has its properties inherited from the parent class:
public class Child extends Parent{
public void print() {
System.out.println("In child");
}
}
This is the class which contains the main method:
public class Main {
public static void main(String[] args) {
Child child = new Child();
((Parent)child).print();
}
}
Clarification
In your example, the object is always Child. Casting is applied only to the reference variable. This casting never impacts the actual object.
Options
As mentioned by others, add a separate method that will call super.() or use hiding. Hiding is not actually overriding.
Beware of the side effects of hiding
public class AccessParent {
public static void main(String[] args) {
Parent p = new Child();
p.methodC();
System.out.println(new String(new char[20]).replace("\0", "-"));
p.methodD();
}
}
class Parent {
void methodA() {
System.out.println("Parent.methodA");
}
private void methodB() {
System.out.println("Parent.methodB");
// this will still call Child.methodA
// a hidden method can not control the scope of overridden method
methodA();
}
void methodC() {
System.out.println("Parent.methodC");
methodB();
}
void methodD() {
System.out.println("Parent.methodD");
// hidden method will be called
// technically Child.methodB() is not overridden
methodB();
}
}
class Child extends Parent {
#Override
void methodA() {
System.out.println("Child.methodA");
}
// this not overridden
void methodB() {
System.out.println("Child.methodB");
}
}
This will output
Parent.methodC
Parent.methodB
Child.methodA
--------------------
Parent.methodD
Parent.methodB
Child.methodA```
You can't access a overriden method directly from a child class. The best you can do is add another function to your child that calls the parent print function.
public class Child extends Parent{
public void print() {
System.out.println("In child");
}
public void printParent() {
super.print()
}
}
Then you can access it like this,
public class Main {
public static void main(String[] args) {
Child child = new Child();
child.printParent();
}
}
Overriding is a principle which gives weightage on inheritance.
If you have a specific requirement to behave as per the casting then the method must be class level "static" instead of instance level.
You would loose the beauty of true inheritance and enter in hiding it more. However, the same can be achieved in casting way
package com.company.language;
public class InheritanceTrial {
public static void main(String[] args) {
Child child = new Child();
child.print();
((Parent)child).print();
}
}
class Parent {
public static void print() {
System.out.println("In parent");
}
}
class Child extends Parent{
public static void print() {
System.out.println("In child");
}
}
With the help of java.lang.invoke.MethodHandles, java.lang.invoke.MethodHandle and java.lang.invoke.MethodType we can only access the immediate parent's method. So this might help your question.
Working solution
public class Child extends Parent {
public static void main(String[] args) throws Throwable {
MethodHandle MH_Parent = MethodHandles.lookup().findSpecial(Parent.class, "print" , MethodType.methodType(void.class), Child.class);
MH_Parent.invokeExact(new Child());
}
public void print() {
System.out.println("In child");
}
}
class Parent {
void print() {
System.out.println("In parent");
}
}
Failing Solution
class Parent {
public void print() {
System.out.println("In parent");
}
}
class Child extends Parent{
public void print() {
System.out.println("In child");
}
}
public class Main {
public static void main(String[] args) throws Throwable {
MethodHandle MH_Parent = MethodHandles.lookup().findSpecial(Parent.class, "print" , MethodType.methodType(void.class), Child.class);
MH_Parent.invokeExact(new Child());
}
}

Q: Abstract class object initiation code?

In this class abstract class object is instantiated by overriding the getNum(), what is the purpose of this?
public abstract class AbstractTest {
public int getNum() {
return 45;
}
public static void main(String[] args) // main function
{
AbstractTest t = new AbstractTest() // From this point didn't understand
{
public int getNum() // function
{
return 22;
}
}; //use of this
System.out.println(t.getNum()); // output
}
}
The instantiation in your main() method is simply an inline class definition of a concrete instance of the abstract class AbstractTest. To be clear, the variable t is an anonymous, non abstract class instance. The following code would achieve the same thing:
public class ConcreteTest extends AbstractTest {
#Override
public int getNum() {
return 22;
}
}
public static void main (String [] args) {
ConcreteTest t = new ConcreteTest();
System.out.println(t.getNum());
}
There are instances in the course of development where it can be cumbersome to have to create a formal class definition. For example, if you only need a single instance of the abstract AbstractTest class, it would be easier to use an inline definition.
We call this 'Anonymous Class': When you need to create and use a class, but do not need to give its name or reused use, you can use an anonymous class. Here is the offical doc. Not only used for abstract class, can also be used for interface and general extensible class.
interface Base {
void print();
}
public static void main(String[] args) {
Base aInterface = new Base() {
#Override
public void print() {
System.out.println("A anonymous implement.");
}
};
Thread aThread = new Thread() {
#Override
public void run() {
super.run();
}
};
}

Method Overriding using super keyword

I have one doubt, Please see the following code. i have three classes A,B and InheritanceExample. Here I am calling the super.run() from the main class; it is calling the B class run() method.
Is there any option to call A class run method from the main class (InheritanceExample) with out creating an instance for class A?
class A
{
void run()
{
System.out.println("<<<====Class A run Method===>>>>");
}
}
class B extends A
{
void run()
{
System.out.println("<<<====Class B run Method===>>>>");
super.run();
}
}
public class InheritanceExample extends B{
/**
* #param args
*/
void run()
{
System.out.println("<<<====Main Class run Method===>>>>");
super.run();
}
public static void main(String[] args) {
InheritanceExample a = new InheritanceExample();
a.run();
}
}
Since B extends A and InheritanceExample extends B you are creating an instance. Make method A.run() static.
class A
{
void static run()
{
System.out.println("<<<====Class A run Method===>>>>");
}
}
class B
{
void run()
{
System.out.println("<<<====Class B run Method===>>>>");
A.run();
}
}
public class InheritanceExample extends B {
#Override
void run()
{
System.out.println("<<<====Main Class run Method===>>>>");
super.run();
}
public static void main(String[] args) {
InheritanceExample a = new InheritanceExample();
a.run();
}
}
No.
Not without making A.run() different from B.run(), such as by making A.run() static.
When B extends A, you as a programmer must ensure that from the callers perspective B "is-a" A. What you want to do is to break this rule.
If you want to use a B as an A, you are probably trying to do something at the calling point, that should be handled internally in B.
Not sure what you want to achieve. But looking at the class hierarchy and structure, it is not possible to directly call run method of Class A. But if we change and introduce a additional static method say runImpl in Class A, and call same method from run method of Class A. Now we can call runImpl from anywhere as it is static and run method too internally is calling runImpl so same implementation is getting call via run and runImpl.
Below is the code snippet:
class A
{
void run()
{
runImpl();
}
public static void runImpl(){
System.out.println("<<<====Class A run Method===>>>>");
}
}
class B extends A
{
void run()
{
System.out.println("<<<====Class B run Method===>>>>");
super.run();
}
}
public class InheritanceExample extends B{
/**
* #param args
*/
void run()
{
System.out.println("<<<====Main Class run Method===>>>>");
super.run();
}
public static void main(String[] args) {
A.runImpl();
}
}
class a{
void run(){
System.out.println("runing method run of a clss");
}
}
class b extends a{
void run(){
super.run();
System.out.println("runing method run of b clss");
}
}
class InheritanceExample extends b{
void run(){
super.run();
System.out.println("running method run in inheritance class");
}
}
class pratics{
public static void main(String[] args){
System.out.println("********");
InheritanceExample a1=new InheritanceExample();
a1.run();
System.out.println("********");
}
}

How to write an abstract main class

I need to write some importers. They need all the same initialization. So I try to write an abstract class, which does all the initialization and also has the main method, so that all sub-classes just need to implement run() to do their specific import work:
public abstract class AbstractImporter {
public AbstractImporter() {
// Initialization
}
public abstract void run();
public static void main(String[] args) {
AbstractImporter importer = new AbstractImporter();
importer.run();
}
}
public class ConcreteClass() {
public void run() {
// Do some importing
}
}
Of course it fails to create an instance of this abstract class (new AbstractImporter()).
Does anybody has any idea how to solve that? TIA!
Obviously you need a concrete class - anonymous or otherwise.
Better to move the main method to another class and instantiate the appropriate concrete class based on data (either your domain specific or a constant) and then run it. This way each implementation can be independent of other implementations.
public abstract class AbstractImporter {
public AbstractImporter() {
// Initialization
}
public abstract void run();
}
public class ConcreteImporter1 extends AbstractImporter {
public void run() {
//do something
}
}
public class ImporterMain() {
public static void main(String[] args) {
AbstractImporter importer = createImporter(args[1]);
importer.run();
}
private static AbstractImporter createImporter(String type) {
if (type.equals("1")) {
return new ConcreteImporter1();
}
....
}
}
new AbstracterImporter() {
public void run() {
// ...
}
};
I apologize for current lack of formatting, currently on a mobile device.
public abstract class AbstractImporter {
public AbstractImporter() {
// Initialization
}
public abstract void run();
public static void main(String[] args) {
AbstractImporter importer = new AbstractImporter(){
public void run() {
System.out.println("Anonymous implementation");
}
};
importer.run();
}
}
You cannot create an instance of an abstract class.
public abstract class AbstractImporter {
public AbstractImporter() {
// Initialization
}
public abstract void run();
}
public class ConcreteClass extends AbstractImporter{
public void run(){
//Implementation
}
public static void main(String args[]){
AbstractImporter ai = new ConcreteClass();
ai.run();
}
}

How to call a method defined while object instantiation?

wondering how it is possible to call public m method?
public class Test1 {
public static void main(String[] args) {
Test1 test = new Test1() {
public void m() {
System.out.println("m");
}
};
}
}
I don't believe you can. You'd have to create an interface or subclass. (Well, okay, that's probably not true. You could probably do it with reflection.)
E.g., like this (where you call it via test.m() after construction):
public class Test1 {
public static void main(String[] args) {
SubTest1 test = new SubTest1() {
public void m() {
System.out.println("m");
}
};
test.m();
}
private static abstract class SubTest1 extends Test1 {
public abstract void m();
}
}
Or like this, where it happens during construction:
public class Test1 {
public static void main(String[] args) {
SubTest1 test = new SubTest1() {
public void m() {
System.out.println("m");
}
};
}
private static abstract class SubTest1 extends Test1 {
public SubTest1() {
this.m();
}
public abstract void m();
}
}
You can't define an anonymous class constructor, so that last uses the constructor of the SubTest1 class and the abstract method.
You cannot directly invoke m since test is of type Test1 which does not contain a method called m, but you should never find yourself in a situation like this. The whole point of anonymous classes is to alter some already-existent aspect of the base class's functionality, so adding new methods makes no sense. Consider rethinking your design or using a named class instead.
Of course, if you won't care about test in the future you could do this:
new Test1() {
public void m() {
System.out.println("m");
}
}.m();
Although you would rarely want to do something like this, it could be useful if you're working with Thread or Runnable and need to invoke the run method.
If Test1 had a method called "m" you could just call test.m() after you instantiated the inner class:
public class Test1 {
public static void main(String[] args) {
Test1 test = new Test1() {
public void m() {
System.out.println("New Behavior");
}
};
test.m();
}
public void m() {
System.out.println ("Default Behavior");
}
}
Running this would output:
New Behavior

Categories