I have a basic class structure like this:
public class A {
}
public class B extends A {
private C objC;
public B() {
this.objC = new C();
}
}
public class C extends A {
private B objB;
public C() {
this.objB = new B();
}
}
I need B and C to know about each other so they can access each other's methods but obviously at runtime this creates a cyclic dependency and results in a java.lang.StackOverflowError: null. I have read this and this but I can't seem to get a good resolution on what I should do in my case.
Is there a better way to approach this?
Edit 1: A more descriptive of my situation while keeping simplicity:
public class A {
}
public class B extends A {
private C objC;
public B() {
this.objC = new C();
}
public String foo1() {
int x = C.foo3();
//do something
return Integer.toString(int);
}
public int foo2() {
// do something
}
}
public class C extends A {
private B objB;
public C() {
this.objB = new B();
}
public int foo3() {
int y = B.foo2();
//do something
return y;
}
}
Use Mediator pattern if you want to establish communication among different objects.
Mediator - defines the interface for communication between Colleague objects
ConcreteMediator - implements the Mediator interface and coordinates communication between Colleague objects. It is aware of all the Colleagues and their purpose with regards to inter communication.
ConcreteColleague - communicates with other Colleagues through its Mediator
Have a look at this link : https://en.m.wikipedia.org/wiki/Mediator_pattern
Related
I have 3 Data Classes
#Data
class A
{
private int a;
}
#Data
class B extends A
{
private int b;
}
#Data
class C extends A
{
private int c;
}
Class B and C have some common fields between them which is kept in their parent class A.
Following is the tester class
class TesterClass
{
static String bOrC = "C"; // input from some decision
public static void main(String[] args) // assume this to be the client
{
A a;
if (bOrC.equals("B")) {
B b = new B();
b.setB(11);
a = b;
} else {
C c = new C();
c.setC(12);
a = c;
}
a.setA(10);
doSomething(bOrC, a);
}
// Below are the service methods
// only this method in the service exposed
public static void doSomething(String bOrC, A a) {
if (bOrC.equals("B")) {
doSomethingWithB(a);
} else if (bOrC.equals("C")) {
doSomethingWithC(a);
}
}
public static void doSomethingWithB(A a) {
B b = (B) a; // possible ClassCastException
System.out.println(b.getA());
System.out.println(b.getB());
}
public static void doSomethingWithC(A a) {
C c = (C) a; // possible ClassCastException
System.out.println(c.getA());
System.out.println(c.getC());
}
}
Now the problem I see with this is unsafe Dynamic Type Casting which can run into Class Cast Problems. One possible solution would be to create separate data objects and set the common fields (which are too many for my actual case) for both the objects separately in both classes B and C which would then look as follows:
public class TesterClass
{
static String bOrC = "C"; // input from some decision
public static void main(String[] args)
{
if (bOrC.equals("B")) {
B b = new B();
b.setA(10); // duplication
b.setB(11);
doSomethingWithB(b);
} else {
C c = new C();
c.setA(10); // duplication
c.setC(12);
doSomethingWithC(c);
}
}
public static void doSomethingWithB(B b) {
System.out.println(b.getA());
System.out.println(b.getB());
}
public static void doSomethingWithC(C c) {
System.out.println(c.getA());
System.out.println(c.getC());
}
}
I'm looking for a way to avoid this dynamic type casting but at the same time avoid having to duplicate the common variables. Can anyone suggest a solution?
Abstraction is one solution for the behavior you are explaining. Creating an abstract method doSomething(...) in class A and implementing it in child class B and C respectively. By doing this you don't need to have a static method and processing will be done bases on the instance of B or C objects itself.
#Data
class A
{
private int a;
public abstract void doSomething();
}
#Data
class B extends A
{
private int b;
public void doSomething(){
/*.... do something here
* here you can also access parent public methods and properties.
* as you have already annotated with #Data you will have access to getA() method, * hence you can also use parent properties.
*/
}
}
#Data
class C extends A
{
private int c;
public void doSomething(){
/*.... do something here
* here you can also access parent public methods and properties.
* as you have already annotated with #Data you will have access to
* getA() method, * hence you can also use parent properties.
*/
}
Now you can use it as below
public static void main(Strings[] args){
A a;
B b = new B();
b.setB(10);
b.doSomething();
C c = new C();
c.setC(30);
c.doSomething();
}
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 following situation and would like to know the best way to design my solution
public abstract class A {
public abstract A getHelper();
public abstract void launchHandle();
public static A initHelper(String condition) throws Exception {
if ( condition == 'xyz') {
return C.getHelper();
} else {
return B.getHelper();
}
}
}
public class B extends A {
protected static A b;
#Override
public A getHelper() {
b = new B();
return b;
}
#Override
public void launchHandle() {
System.out.println("Launching Handle");
}
public String getName() {
return "I am from Class B";
}
}
public class C extends A {
protected static A c;
#Override
public A getHelper() {
c = new C();
return c;
}
#Override
public void launchHandle() {
System.out.println("Launching Handle from C");
}
public String getValue() {
return "I am from Class C";
}
}
**Executor class**
public class Executor {
public static void main(String[] args) {
A aa = a.initHelper(condition);
}
}
Now in the above approach, i am unable to access methods like aa.getName() from Class B OR aa.getValue() from Class C, which makes sense. However how to get these methods in executor class? Executor does not know anything about Class B & C and should not know. Executor is only aware of Class A, but want to access methods SubClass methods from B & C which are extended from Class A.
Please help design this and what could be best way to solve this.
Thanks in advance.
Executor is only aware of Class A, but want to access methods SubClass methods from B & C which are extended from Class A.
If you take a closer look at your code, you will notice that the only contract constant across all your classes is the launchHandle method (baring getHelper and initHelper which are simply used for instantiating the right subclass). There is no real relation between B and C other than the fact that their instantiation is controlled by A.
This is how I would consider approaching the problem :
Executor Factory
Make Executor an abstract class rather than making it the entry point of your program :
public abstract class Executor {
public abstract void performTask();
public static void execute(String condition) {
Executor executor = null;
if ( condition.equals("xyz")) {
executor = new AExector();
} else {
executor = new BExecutor();
}
executor.performTask();
}
}
Executor implementations
Create a different implementation for operating on B called BExecutor :
public class BExecutor extends Executor {
public void performTask() {
System.out.println("launching handle from B");
//create or get data to perform the task on
B b = new B();
String name = b.getName();
System.out.println("I am from "+name);
}
}
Create a different implementation for operating on C called CExecutor :
public class CExecutor extends Executor {
public void performTask() {
System.out.println("launching handle from C");
//create or get data to perform the task on
C c = new C();
String value = c.getValue();
System.out.println("I am from "+value);
}
}
Your main method can then look like this :
public static void main(String []args) {
Executor executor = Executor.execute(condition);
}
And for some reason, if you do find some common contract between B and C, you an always create an interface which both B and C can implement and use a reference of this interface instead of using a B or C reference.
Add getName and getValue to A as abstract methods.
I want to ask you something more on this matter for the below code for SOLID. If all these 3 classes are are following SOLID concept.
public interface A {
public void calculate(String a);
}
public class B implements A {
#Override
public void calculate(String b) {
System.out.println("value: " + b);
}
}
public class C {
private A a;
public void show() {
a = new B();
a.calculate("test");
}
}
From how I look at things,
Class C breaks the
Single Responsibility Principle by handling two responsibilities, namely, instantiating other objects(instance of B) and the show functionality whatever that is. Object creation should be handled by a separate class and the dependencies should be injected to the users.
Open Closed Principle by being tightly coupled to B, whereas it could have depended on the interface A, thus being open for extension by using another implementation of A. See this for more information. In other words, C should have used A, and the actual implementation should have been injected to C.
Following is how you could write C to be SOLID.
class C {
private A a;
public C(A a) {
super();
this.a = a;
}
public void show() {
a.calculate("test");
}
}
class Creator {
C createC() {
A b = new B();
return new C(b);
}
}
Creator could be replaced by a dependency injection framework like Spring.
I hope the below code snippet is following SOLID strongly.
public class Creator {
public static A getA(){
A a = new B();
return a;
}
}
public class C {
private A a;
public void show() {
setB();
a.calculate("test");
}
private void setB(){
a = Creator.getA();
}
}
Consider following situation. I want to achieve the different behavior for methoddA() of class A depending upon from where it is getting call like here from class D or class C. How this can be achieved, method overriding is not working here.
class A
{
public methodA(){ //some code }
}
class B
{
A a = new A()
public methodB()
{
a.methodA();
}
}
class C
{
B b = new B();
public methodC()
{
b.methodB();
}
}
class D
{
B b = new B();
public methodD()
{
b.methodB();
}
}
What you need here is Polymorphism. First create an interface -
public interface MyInterface
{
void methodA();
}
then create two different implementations for two different behaviors -
public class First implements MyInterface
{
public void methodA() {
// first behavior
}
}
public class Second implements MyInterface
{
public void methodA() {
// second behavior
}
}
Now create your other classes as follows -
class B
{
public void methodB(MyInterface m)
{
m.methodA();
}
}
class C
{
B b = new B();
public void methodC()
{
// Pass the corresponding behavior implementation
// as argument here.
b.methodB(new First());
}
}
class D
{
B b = new B();
public void methodD()
{
// Pass the second behavior implementation.
b.methodB(new Second());
}
}
This will result in a more maintainable code.
You can pass the class name to your method as a String and in your method check
if(className.equals("A") // or use isInstanceOf() if you are passing objects of A/B
//do something
if(className.equals("B")
// do something else.
Why do you need two different implementations?
This easy trick can work for you... Please correct me if i am wrong..
I following code I have modified the method signature of Class A1 and Class B1 to accept Object and similarly while calling the methods from Class C and Class D whereever we are calling this method of class B1 pass this as reference. In Class A1 we can then check instanceof object and identify the calling class.
class A1
{
public void methodA(Object c){ //some code }
if (D.class.isInstance(c)){
System.out.println("Called from Class D");
}else if (C.class.isInstance(c)){
System.out.println("Called from Class c");
}else{
System.out.println("Called from Some diff class");
}
}
}
class B1
{
A1 a = new A1();
public void methodB(Object c)
{
a.methodA(c);
}
}
class C
{
B1 b = new B1();
public void methodC()
{
b.methodB(this);
}
}
class D
{
B1 b = new B1();
public void methodD()
{
b.methodB(this);
}
}
public class Testnew{
public static void main(String args[]){
D d = new D();
d.methodD();
C c = new C();
c.methodC();
B1 b = new B1();
b.methodB(b);
}
}