The most obvious case of circular reference is self-reference. Self reference are basis of linked lists, trees, and lots of other recursive structures. The self reference is necessary because all classes are of same type that either linked or have an reference to a child that is a also of type same.
Another common case of circular referencing is bidirectional parent-child relationship. A parent (e.g. a UI panel) holds a reference to an array of its children, and each child (e.g. buttons, tables, etc.) holds a references to the parent. The parent needs to send notifications to its children to tell them that it became enabled, disabled, visible, or invisible; a child may notify the parent of the need to resize, change visual state, etc.
Another example of circular reference is like Creature-CreatureAI pair. They are separate because their concerns are dissimilar, but they have references to each other because they need to cooperate on different tasks.
There any number of reasons for self reference. To list of few
- They may be inherent in the domain model; e.g. people have children who are also people, folders contain other things including other folders. A self reference or cycle is a natural way to implement these things.
- They may be inherent to a generic or application specific data structure; e..g. a linked list consists of nodes which include references to the “next” and “previous” node in the list, and this requires the Node class to refer to itself.
- The reasoning behind the cyclic reference can be a fundamental part of the design of the application.
- Or, it can simply be an implementation convenience, or a historical artefact of previous refactorings or code-base evolution.