Okay so this has been an issue I keep running across. Now there are plenty of ways to do this, but I am wondering what you consider to be 'best practice'
Suppose we have project structure as follows:
Java Project:
src/
PackageA/
ClassA.java
PackageB/
ClassB.java
ClassC.java
Main.java
Each class is as follows:
public class Main {
private ClassA classA;
private ClassB classB;
public Main(){
}
public void runMainMethod(){
//Init Objects
classA = new ClassA();
classB = new ClassB();
classA.getDataFromClassC();
}
}
public class ClassA {
public ClassA(){
}
public void getDataFromClassC(){
//Best way to get Data from classC?
}
}
public class ClassB {
private ClassC classC;
public ClassB(){
loadClassC();
}
private void loadClassC(){
classC = new ClassC("ExampleName");
}
}
public class ClassC {
private String name;
public ClassC(String name){
this.name = name;
}
public String getNam(){
return name;
}
}
I feel like passing Main through each class and creating a getter method in Main (for classB), and then another getter Method in B (for classC) is overkill.
Especially if it goes deeper. What if class C holds an object Class D? And I wanted to access class D from Class A?
Maybe I am not performing the best practice for OOP?
Any information on how you handle this, or a better practice would be greatly appreciated!
Question2:
What if, you only want one ClassB (Maybe because ClassC was loaded from a file, and multiple ClassB's will not be syncronized in respect to the class C).
Ex I want to avoid this issue:
ClassC classC = new ClassB().getClassC();
ClassC2 classC2 = new Class().getClassC();
classC.setName("C");
classC2.setName("C2);
where both classes have different name values
Related
Let's assume we have 2 classes in Java 8, ClassA and ClassB. ClassA is a dependency class which cannot be changed in any way. ClassB is kind of like a copy of ClassA but with some modifications. ClassB cannot extend ClassA, but has almost the exact same functions as ClassA.
public class ClassB {
public ClassB(...) {}
public int update(...) {}
public String query(...) {}
.
.
.
}
So the above structure is similarly present in ClassA as well.
Say I want to code 2 other classes ClassC that uses an instance of ClassA and ClassD that uses an instance of ClassB. ClassC and ClassD have the exact same code except for the instances of ClassA and ClassB.
public class ClassC {
ClassA tmp;
public ClassC(...) {
tmp = new ClassA(...);
}
public void doSomething(...) {
tmp.update(...);
tmp.query(...);
}
.
.
.
}
public class ClassD {
ClassB tmp;
public ClassD(...) {
tmp = new ClassB(...);
}
public void doSomething(...) {
tmp.update(...);
tmp.query(...);
}
.
.
.
}
From the examples, it can be seen that ClassC and ClassD have the same functions but use a different Class for tmp
Is there any way that code duplication can be avoided? Can there be some way that I can write most of the functions of ClassC and ClassD as generic code and then have ClassC and ClassD extend this generic code?
Attempts at a solution
I tried a way that basically creates an interface class in a weird way. I define a ClassE that creates abstractions of ClassA and ClassB functions and also implements all the functions of ClassC and ClassD
public abstract class ClassE {
public ClassE(...) {}
public abstract int update(...);
public abstract String query(...);
public void doSomething(...) {
tmp.update(...);
tmp.query(...);
}
.
.
.
}
Then basically, ClassC and ClassD extend ClassE
public class ClassC extends ClassE {
ClassA tmp;
public ClassC(...) {
tmp = new ClassA(...);
}
public int update(...) {
return tmp.update(...);
}
public String query(...) {
return tmp.query()
}
.
.
.
}
public class ClassD extends ClassE {
ClassB tmp;
public ClassD(...) {
tmp = new ClassB(...);
}
public int update(...) {
return tmp.update(...);
}
public String query(...) {
return tmp.query()
}
.
.
.
}
Is this the best approach to the problem? Can there be a more suitable approach?
you could create an interface, not an abstract class. A generic interface. It would be as follows:
public interface class ClassE <G> {
int update(G attr);
String query(G attr);
void doSomething(G attr);
}
You must create the class implements:
public class ImplementClassA implements ClassE<ClassA> {
public int update(ClassA attr){
.
.
.
}
public String query(ClassA attr){
.
.
.
}
public void doSomething(ClassA attr){
.
.
.
}
}
public class ImplementClassB implements ClassE<ClassB> {
public int update(ClassB attr){
.
.
.
}
public String query(ClassB attr){
.
.
.
}
public void doSomething(ClassB attr){
.
.
.
}
}
In class c, interfaces could be used. In ClassC, you could use the interfaces, so you pass the instance of the type you need, be it the implementation of ClassA or ClassB
public class ClassC <G> {
private ClassE tmp;
public ClassC(ClassE tmp) {
this.tmp = tmp;
}
public int update(G attr) {
return tmp.update(attr);
}
public String query(G attr) {
return tmp.query(attr)
}
.
.
.
}
Ex,:
ClassC<ClassA> teste = new ClassC<ClassA>(new ImplementClassA());
ClassA save = new ClassA();
teste.update(save);
ClassC<ClassB> teste2 = new ClassC<ClassB>(new ImplementClassB());
ClassB save2 = new ClassB();
teste2.update(save2);
What comes to mind here is what domain driven design calls an anti corruption layer.
Meaning: you create an abstraction around the parts you want to separate yourself from, and your code only uses your own abstractions
In your case:
You create some interface that contains the functionality your classes C and D will want to use
you create two implementations of that interface, one using a class A object, the other one derives its functionality from a class B object
Now your classes C and D just need to be passed the corresponding impl classes. They rely on your interface only, so you are free to refactor them as you find useful.
And note: creating your own interface is the best solution here. Your classes A and B do not have any "type" relationship. Therefore generics aren't of any help here.
I think you are probably hoping for something that is called "duck typing". That is a concept from other languages, where you say "being a duck means: it can quack() and it can walk()" for example. That would mean: when two different classes share certain methods, you can have a "view" that defines a type that has these methods, and both these classes are of that "view type". But java doesn't support that (scala does, btw), and generics don't help with that.
You can create a delegate class for ClassA and ClassB:
public class delegateAB {
private ClassA a;
private ClassB b;
public delegateAB(ClassA a) {
this.a = a;
}
public delegateAB(ClassB b) {
this.b = b;
}
public int update(...) {
return a!=null?a.update(...):b.update(...)
}
// ... other common delegated methods.
}
And then you can instantinate this class either with ClassA or ClassB, so from that point you can use the delegate class in your code, like this:
public class ClassCD {
DelegateAB tmp;
public ClassCD(ClassA a, ...) {
tmp = new DelegateAB(a);
}
public ClassCD(ClassB b, ...) {
tmp = new DelegateAB(b);
}
public void doSomething(...) {
tmp.update(...);
tmp.query(...);
}
.
.
.
}
It's not an exceptionally nice solution but it does the trick.
I have 2 classes, and I have made one class (Class A) instantiate a Class B object.
I have a method in Class B that I want to call a method in Class A.
I'm working on a larger project for practicing Java, so I am simplifying things here.
// Class A:
public class ClassA {
private int number;
private ClassB instanceOfB = new ClassB();
public ClassA {
number = 0;
}
public void incrementNumber {
number++;
}
public void incrementNumberLongWay {
instanceOfB.incrementNumberInA()
}
}
// Class B:
public class ClassB {
public void incrementNumberInA() {
// My desire: Call Class A's incrementNumber method
// What should I put here?
}
}
How do I make sure incrementNumberLongWay works? Class A has been instantiated, and it's method incrementNumberLongWay is called, so this should call ClassB's method incrementNumberInA
I know this seems extremely convoluted, but the reason I'm doing this, is because in my program I'm not incrementing numbers, but instead doing some logic in Class B, and only wanting to affect Class A in certain cases.
You can't do this with the code provided. Relationships are by default one way. B doesn't know about A so cannot access it.
What you can do is pass a reference of A to B in it's construction process and then access A via that reference.
One solution would be to pass a method of A as a callback.
For example:
public class ClassA {
private int number;
private ClassB instanceOfB = new ClassB();
public ClassA {
number = 0;
}
public void incrementNumber {
number++;
}
public void incrementNumberLongWay {
instanceOfB.incrementNumberInA(this::increment);
// alternatively
// instanceOfB.incrementNumberInA(() -> incrementNumber());
}
}
public class ClassB {
public void incrementNumberInA(Runnable callbackMethod) {
callbackMethod.run();
}
}
This removes B's dependency on A, and instead allows a general callback mechanism.
However, for such a simple scenario this approach isn't advised.
It's probably a bad idea in general to have a circular dependency in this way. One approach to break the cycle would be to have a third class (classC?) that implements the increment logic (or whatever your real-world equivalent is), and have classA and classB instances each reference classC. That way there's no case where two classes know about each other.
ClassB doesn't know anything about ClassA. So, you couldn't do it.
The ugly decision is
public void incrementNumberLongWay() {
instanceOfB.incrementNumberInA(this);
}
and in
public class ClassB {
public void incrementNumberInA(ClassA cl) {
cl.incrementNumber();
}
}
You can't call methods from class A from class B as class B has no reference to an object of class a. You could, however, pass class A's current number state to class B as parameter, and return a value from class B which class A can then get and use.
For example:
public class A {
private int number;
public A(int number) {
this.number = number;
}
public void incrementNumber(boolean largeIncrement) {
if(largeIncrement) {
B bInstance = new this.B();
number = bInstance.incrementNumberLongWay(number);
}
else {
number++;
}
}
private class B {
private B() {
// if some initialization is needed...
}
public int incrementNumberLongWay(int num) {
num += 1000;
return num;
}
}
}
Hope this is what you wanted.
i created two classes, each one is in a different package ... here is the class inside the main package:
package Main;
public class Main {
Public static void main(String [] args ) { .....}
}
// class in main package
class ClassS{
public int publicAtttibute;
private int pricatdAttribute;
And this is the second class in another package:
package second;
public class ClassC{
public static void doSomething(){
ClassD ref = new ClassD();
} }
But i’m not sure if this code makes the classD and it’s attributes visible to class c, can someone please clarify it
You defined an instance object of classD inside the classC which means that ClassD and all of it’s public attributes would NOT be visible to ClassC ..... if you want the ClassD to visibile but the attributes aren’t you could code it like this:
package other:
public class ClassC{
public static void visible(){
ClassD ref = new ClassD();
ref.publicAttribute = 3;
ref.privateAttribute=3;
}}
Being new to Java but an old hand on older procedural languages and structured programming, I have a question on how to accomplish something in Java
I have three classes, let's say they're called CLASSA, CLASSB, and TESTCLASSA. CLASSA has a class definition with instance variables, and a constructor for some data. TESTCLASSA creates an instance of CLASSA and passes data to CLASSA by creating an instance of the object for CLASSA. SImiliarly CLASSB has another class definition with instance variables, and a constructor for some data. TESTCLASSA creates an instance of CLASSB and passes data to CLASSB by creating an instance of the object for CLASSB. I am trying to access CLASSB's data from CLASSA. Can someone suggest how I might go about doing this. Many thanks in advance for any assistance/suggestions you can provide.
Wayne Hann
Either declare the variable as public:
public class classA {
public Integer data;
}
or create a public getter (preferred), such as:
public class classA{
private Integer data;
public Integer getData() {
return data;
}
}
If you want to access properties of class B from class A then it's either possible that you create a object of B in the method from where you want to getData like
private String nameofA;
public String getNameofA() {
return nameofA;
}
public void setNameofA(String nameofA) {
this.nameofA = nameofA;
}
public String getClassBData(){
B b = new B();
return b.getNameofB();
}
else you create a class level instance or dependency of B type.
public class TestClassA{
public static void main(String[] args) {
B b = new B();
b.setNameofB("class B Name");
A a = new A("class A Name",b);
}
}
class A{
private String nameofA;
private B b = new B(); //either this
public String getNameofA() {
return nameofA;
}
public A(String nameofA, B b) {//or constructor
super();
this.nameofA = nameofA;
this.b = b;
}
public void setNameofA(String nameofA) {
this.nameofA = nameofA;
}
public String getClassBData(){
B b = new B(); // or creating local instance
//but here a new instance will be created
return b.getNameofB();
}
}
Then only you will be able to access the data of instance of B. Anyway you if your method in B is not private or protected(assuming A doesn't extend B), you can access the method by creating or passing a instance of B to the method of "A" from where you want to access.
I have a requirement as follows. I have loaded a set of classes [present in a jar file] using Reflection in java. Now in the loaded class, I want to call certain methods in the loading class.
For example, assume class A and class B are there. Using reflection I am loading class B from class A. Therefore I am able to use the methods in class B from class A. But I want to use some methods in class A from class B.
Your help is greatly appreciated.
Thanks..
It seems like a faulty design. Try to rethink it. Your current setup may be solved by applying a singleton pattern. For example:
abstract class SomeSingleton {
private static SomeSingleton instance;
public static void setInstance(SomeSingleton instance) {
this.instance = instance;
}
public static SomeSingleton getInstance() {
return instance;
}
public abstract void someMethod();
}
class ClassA extends SomeSingleton {
public ClassA() {
SomeSingleton.setInstance(this);
}
#Override
public void someMethod() {
System.out.println("some methid is called");
}
}
class ClassB {
public void aMethod() {
SomeSingleton.getInstance().someMethod();
}
}
This way ClassB does not have to know about ClassA. It only knows about a service. ClassA reports to SomeSingleton that it can provide the service. - So everyone is happy.
You could insist that your class B (the loaded class) has a constructor which takes A as a parameter:
class B {
public B(A a) {
// etc...
}
}
And then in your reflection code, instantiate the class with that constructor. B can now do whatever it needs with A. You can create a new instance for a specific constructor like this:
Class<B> clazz = B.class;
clazz.getConstructor(new Class[] {A.class}).newInstance(a);
You could let classB implement a method through which you provide an instance of classA and then use this instance from inside classB.
You can ONLY do this by explicitly telling your instance of classB about classA, e.g. by calling
b.setA(this)
from a.