How to design a class to prevent circular dependencies from calling derived members before construction?

c#, circular-dependency, inheritance, java, oop

Solution

Personally, I don't like circular references. But if you decide to leave them, you may add some laziness:

interface IKernel
{
    // Useful members, e.g. AvailableMemory, TotalMemory, etc.
}

class Kernel : IKernel
{
    private readonly Lazy<FileManager> fileManager;  // Every kernel has 1 file manager
    public Kernel() { this.fileManager = new Lazy<FileManager>(() => new FileManager(this)); /* etc. */ }

    // implements the interface; members are overridable
}

class FileManager
{
    private /*readonly*/ IKernel kernel;  // Every file manager belongs to 1 kernel
    public FileManager(IKernel kernel) { this.kernel = kernel; /* etc. */ }
}  

Laziness here lets ensure, that IKernel implementation will be initialized completely, when FileManager instance will be queried.

Problem

(I tagged this as both C# and Java, since it's the same question in both languages.) Say I have these classes ``` interface IKernel { // Useful members, e.g. AvailableMemory, TotalMemory, etc. } class Kernel : IKernel { private /*readonly*/ FileManager fileManager; // Every kernel has 1 file manager public Kernel() { this.fileManager = new FileManager(this); /* etc. */ } // implements the interface; members are overridable } class FileManager { private /*readonly*/ IKernel kernel; // Every file manager belongs to 1 kernel public FileManager(IKernel kernel) { this.kernel = kernel; /* etc. */ } } ``` The problem with this design is that as soon as `FileManager` tries to do anything inside its constructor with `kernel` (which it might reasonably need to), it will be calling a virtual method on a potential subclass instance whose constructor is not yet called. This problem doesn't occur in languages where you can define true constructors (rather than initializers, like C#/Java), since then the subclasses don't even exist before their constructors are called... but here, this problem happens. So what is the best/proper design/practice, to ensure this doesn't happen? Edit: I'm not necessarily saying I need circular references, but the fact is that both `Kernel` and `FileManager` depend on each other. If you have a suggestion on how to alleviate this problem without using circular references, then that's great too!

Original source