Java mutual dependency with interfaces set in constructor - java

I have 2 classes that rely on each other and they both have their respective interfaces. However, I cannot setup the constructor on both classes cleanly. In short, one class needs to be instantiated before the other class gets instantiated.
Class A implements IA {
public A(IB b) {
myBclass = b;
}
private IB myBclass;
}
Class B implements IB {
public B(IA a) {
myAclass = a;
}
private IA myAclass;
}
static void main(String[] args) {
A a = new A(null);
B b = new B(a);
a.setB(b); // how can I avoid doing this
}
I would like to avoid setting member variables outside the constructor.

You can have one construct the other.
class A implements IA {
private IB myBclass;
public A() {
myBclass = new B(this);
}
// etc.
}
class B implements IB {
private IA myAclass;
public B(IA a){
myAclass = a;
}
// etc.
}
That way you don't have to alter them after construction.
public static void main(String[] args){
A a = new A();
B b = a.getB();
}

Related

How to solve this method override and polymorphism problem that have different scope?

What will be the result of attempting to compile and run the following program?
public class Main {
public static void main(String[] args) {
A ref1 = new C();
B ref2 = (B) ref1;
System.out.println(ref2.g());
}
}
class A {
private int f(){
return 0;
}
public int g(){
return 3;
}
}
class B extends A{
private int f(){
return 1;
}
public int g(){
return f();
}
}
class C extends B{
public int f(){
return 2;
}
}
I tried it and got the answer 1, but I didn't know why.
I modified the following code:
public class Main {
public static void main(String[] args) {
A ref1 = new C();
B ref2 = (B) ref1;
System.out.println(ref2.g());
}
}
to
public class Main {
public static void main(String[] args) {
A ref1 = new C();
System.out.println(ref1.g());
B ref2 = (B) ref1;
System.out.println(ref2.g());
}
}
Its output is
1
1
I can't understand why both ref1 and ref2 are 1 regardless of whether the type is cast to B.
However, if I remove both public and private, like this
public class Main {
public static void main(String[] args) {
A ref1 = new C();
B ref2 = (B) ref1;
System.out.println(ref2.g());
}
}
class A {
int f(){
return 0;
}
int g(){
return 3;
}
}
class B extends A{
int f(){
return 1;
}
int g(){
return f();
}
}
class C extends B{
int f(){
return 2;
}
}
The output becomes 2.
I wonder if this has something to do with private and public too?
My understanding is:
ref1 is of class A and refers to class C.
The superclass of C is B.
The f() method in class B is private, that is, the subclass is "hiding", so it has not been "copied" to the subclass C, so it seems to be overriding, but it is actually a new method belonging to the subclass C, but it "just happens" to have the same name as the method in the parent class.
Moreover, there is no g() in class C, so g() in B is used, and the return is f() in class B.
So the result is 1.
However, if the private and public are removed, then C can override the
f() method in B, and at this time g() will be linked to the f() method of C.
Is my understanding correct?
Thank you very much.

How to make class that can only be accessed through interface?

In C# or Java, how can I make a class that can only be instantiate with the Interfaces it implemented on?
Sorry if this question is asked before.
Edit: Sorry for confusing you, and this question is just asked out of curious:
For example I have:
interface iA
{
int addNum();
}
interface iB
{
int minusNum();
}
class A implements iA, iB
{
private int A;
public int addNum()
{
A += 10;
return A;
}
public int minusNum()
{
A -= 10;
return A;
}
}
class TestIface
{
public static void main(String args[]) {
A testA = new A();
iA testiA = new A();
iB testiB = new A();
testA.minusNum(); // No error, it has access to both methods
testA.addNum();
testiA.minusNum();//ERROR
testiA.addNum();
testiB.minusNum();
testiB.addNum();//ERROR
}
}
I wonder if there is a way to prevent dev from just make testA and access both methods.
How about making the constructor private?
class A implements iA
{
public int returnNum()
{
return 10;
}
private A(){}
public static iA getInstance(){
return new A();
}
}
You can make the constructor private and define a static Create method that creates new instances.
public interface ITest
{
}
public class A : ITest
{
private A()
{
}
public static ITest Create()
{
return new A();
}
}
Then the only way to create an instance of your class (besides reflection, but that's another story!) is to call the Create method like this:
ITest test = A.Create();
You cannot instantiate something via an interface. You can only declare it as an interface. If your goal is to make addNum only accessible via iA and minusNum only accessible via iB, you can try explicit interface implementation (although it has its own drawbacks):
class A : iA, iB
{
private int A;
int iA.addNum()
{
A += 10;
return A;
}
int iB.minusNum()
{
A -= 10;
return A;
}
}
This will at least give you the compile time effect you are looking for:
class TestIface
{
public static void main(String args[]) {
A testA = new A();
testA.minusNum(); // does not compile
testA.addNum(); // does not compile
iA testiA = new A ();
testiA.minusNum();//does not compile
testiA.addNum();
iB testiB = new A ();
testiB.minusNum();
testiB.addNum();//does not compile
}
}
However, this does not mean addNum is only accessible via a variable which is declared as iA. To illustrate, you can do:
A testObj = new A ();
(testObj as iA).addNum (); // this will compile
You can even do:
iB testObj = new A ();
(testObj as iA).addNum (); // this will also compile, and execute fine
If you want to further prevent the explicit casting from and to the concrete class, you need have to take the advice others have offered: make your concrete class a nested private class and introduce a factory to produce the instance:
class Factory
{
private class A : iA, iB
{
int iA.addNum () {...}
int iB.minusNum () {...}
}
public iA GetInstanceOfiA ()
{
return new A ();
}
public iB GetInstanceOfiB ()
{
return new A ();
}
}
This still does not prevent the casting from iA to iB, which I guess you have to create two separate concrete classes to cater.

Best way to share updated data between classes in java

I am working on a projects and I have run into a problem, I don't know the best way to share updated data between classes. The current way that I am doing this is by having a static instance of my class in it and having all the other classes change the instance and not the original class.
public class A{
public static volatile instance;
public B b = new B();
public C c = new C();
public D d = new D();
public A(){
this.instance = this;
b.changeData();
}
}
public class B{
public void changeData(){
A.instance.d.changeSomethingInD();
}
}
Now, all the changes that D made to its variables can be accessed by B and C. Is there a better way to do this?
Edit 1: The problem that I have is having updated variables accessible to all the other classes. This was what I was doing before:
public class MainClass extends JavaPlugin{
private RegionLoader rLoader;
private ClassesLoader cLoader;
private MessageHandler mHandler;
private PlayerDates pDates;
public MainClass(){
dirMaker();
mHandler = new MessageHandler(this);
pDates = new PlayerDates(this);
cLoader = new ClassesLoader(this);
rLoader = new RegionLoader(this);
}
//getters and setters
}
But the problem is if the RegionLoader changes somithing within itself, the ClassesLoader won't have the updated variables and will work with the old ones, or would it?
Why not just pass A into the constructor of B. This way you wouldn't need to use static data.
public class A{
public B b;
public C c = new C();
public D d = new D();
public A(){
b = new B(this);
b.changeData();
}
}
public class B{
private A a;
public B(A a){
this.a = a;
}
public void changeData(){
a.d.changeSomethingInD();
}
}
You could also checkout the observer pattern.

Java: how does a component know its owner

Suppose I have a class A and a class B.
public class A {
private B b;
public A() {
this.b = new B();
}
public B getB() {
return this.b;
}
}
public class B {
public String getSome() {
return "Get some!";
}
}
I know I can get B through A, because A has (or owns) B: new A().getB().
But if I have B, can I get A?
Sure, just add routine getA() in you class B, and change the line in your constructor to
public A() {
this.b = new B(this);
}
This of course assumes your class B has a constructor which accepts an A, e.g.,
public B(A a) {
this.a = a;
}
B needs an explicit reference to its owner:
public class B {
private final A owner;
public B(A owner) {
this.owner = owner;
}
public A getOwner() {
return owner;
}
}
And in A:
public A() {
b = new B(this);
}
Nope. There is no such thing as an 'owner' in Java. Any object can be referenced by any number of other objects.
If you need B to always be bound to an instance of A, make B an inner class of A:
class A {
B b = new B();
class B {
String getSome() {
// this will refer to the enclosing A
return A.this.toString();
}
}
}
An inner (non-static) class always has an implicit reference to the enclosing instance and cannot exist without it. In order to instantiate B from outside, you need a nasty syntax: B b = new A().new B();
No you cannot. B has no reference to A.
No.
Class a has reference to class B, but class B has no reference to class A. References are one way only.
No, that's not possible. You're looking for backreferences, but we have to create them in the code if needed.
If you want to collect all referencers to B, you could do this with a constructor or with a factory (pattern) that creates B's. I'll show the factory:
public class B {
private static Set<? extends Object> referencers = new HashSet<? extends Object>();
private B(){} // no public constructor
public static create(Object parent) {
// cooperative approach, the caller should pass "this"
referencers.add(parent);
}
public static remove(Object parent) {
referencers.remove(parent);
}
}
you can also use inner classes
package test;
public class A {
B b = null;
public B getB()
{
return b;
}
public class B {
public A getA()
{
return A.this;
}
}
public static void main(String[] args) {
B b = new A().new B();
}
}

Two questions on inner classes in Java (class A { class B { } })

Sorry for the bad title, but I couldn't think of a better one.
I'm having a class A and a class B which is kind of a sub class of A, like so:
(Is there actually a correct name for it? Isn't "sub class" reserved for inheritance?)
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
B b = a.new B();
A c = ??? b ??? // get "a" back
}
}
From B every property of A can be accessed, therefore both, a.i and b.i, return 0. Now, I'm wondering whether it's somehow possible to retrieve the original object of type A out of b, as b contains everything that a contains? Simple casting apparently doesn't do the trick.
Second one:
class A {
void print() {
System.out.println("This is class A.");
}
class B {
void print() {
// <--- How to access print() of class A (like this.A.print() or smth)?
System.out.println("This is class B.");
}
}
}
You could alternatively also provide me with some good resources on this topic, as I've been too stupid to find a good one so far.
Thanks in advance. :)
There doesn't seem to be a way to access the outer class from outside. But you can do it like this:
class A {
int i = 0;
class B {
final A outer = A.this;
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = b.outer // get "a" back
}
}
ClassName.this will be the instance of the outerclass associated with the instance of an inner class.
You can access it with the ParentClass.this syntax from within the inner class.
e.g.
public class Outter
{
class Inner {
public Outter getOutter()
{
return Outter.this;
}
}
public Inner getInner(){
return new Inner();
}
}
class Runner{
public static void main(String[] args){
Outter out = new Outter();
Outter.Inner inner = out.getInner();
System.out.println(inner.getOutter().toString());
}
}
[Edit: My answer is appropriate for C# programmers, but I can't guarantee that its applicable to Java.]
B is an inner class, not a subclass of A. Additionally, B does not hold an instance of A, so your code as is cannot return any instance of A.
You need to restructure your classes as follows:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
}
Now your B class has a field 'Parent' which returns its parent. You can use these classes as follows (this is C# syntax, because I don't know if Java has a different syntax for instantiating inner classes):
public static void Main(String[] args)
{
A parent = new A();
A.B child = new A.B(child);
A backToParent = child.Parent;
}
Of course, creating your B class in this way seems little funny: technically, you can pass in any parent. It would probably be better to rewrite your A class with a method which returns a B:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
public B getChild()
{
return new B(this);
}
}
public static void Main(String[] args)
{
A parent = new A();
A.B child = A.getChild();
A backToParent = child.Parent;
}
this seemed to work for me
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = (A)b.getClass().getDeclaredField("this$0").get(b);
}
}

Categories

Resources