How to Handle Cyclical Dependency Between Two Classes in OOP?

This is about OOP. I will keep this brief.

I have classA and classB. classA has an attribute that references an object of classB and contains a static variable that stores all objects of its class. From classB, I want to get a specific classA object. This leads to a cyclical dependency, and I am not sure what the best approach to this problem is.

Any help will be appreciated.

1 Like

Two suggestions:
1 - You can use require(classA) only inside of the classB function that needs classA, although requiring takes a bit more CPU time than just using a predefined variable, so this might not be great for a commonly called function.
2 - Maybe you could have some other class or module that accesses classA for classB, which is only created when an instance of classB is created.

I don’t use Luau OOP that often, so someone else might have better suggestions than me.

1 Like

Thanks for your reply. I forgot to mention that each classA object creates a classB object and stores it as an attribute. (edited post) Thus, your first suggestion unfortunately does not work in my case. Your second suggestion could work, but introducing a new module would probably overcomplicate things.

This is caused by a design flaw… maybe combining the two classes is best, but I want to keep them separate…

Hopefully someone has a clean solution to this problem.

If your classes are interdependent on each other it might be a sign of them being structured incorrectly. I’ve done this before. I think in my case I had a “squad” and “plane” modules for a dogfighting simulation. I had the squad control the planes (so squad depended on plane) but then I had the planes convey info to the squad (to get the position of the center of the squad), so now plane depends on squad too.

The best solution I could come up with was that squad should indeed hold planes, but planes should have no interaction with squads. In this case, I made the squad simply tell the planes where to go, and the planes would listen to that input and simply move. You can replace “squad” and “plane” with classA and classB respectively to get an idea of what you might need to do. In simpler terms, the hierarchy should be from most control to least control, at least in my case.

A fleet can have multiple squads. A squad can have multiple planes, a plane is an independent unit.
With that, I can draw it out in my head like
Fleet → table of <Squad> → table of <Plane>
and enforce that I’m never climbing back up that hierarchy in the opposite direction. Give classB total control over classA instances, and if classA needs some static variable or something similar, either pass it in the constructor of classA or build a Constants class to hold that variable if it is truly static.

4 Likes

Thank you very much for your detailed reply. Your example was great as I have a pretty similar scenario. I now have a much more clear idea of how to solve this problem. I found these statements to be especially helpful!

1 Like