(Я пометил это и как C#, и как Java, поскольку это один и тот же вопрос на обоих языках.)
Скажем, у меня есть эти классы
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. */ }
}
Проблема с этим дизайном заключается в том, что как только FileManager
попытается сделать что-нибудь внутри своего конструктора с помощью kernel
(что может быть обоснованно необходимо), он будет вызывать виртуальный метод для потенциального экземпляра подкласса, конструктор которого еще не называется.
Эта проблема не возникает в языках, в которых можно определить настоящие конструкторы (а не инициализаторы, такие как C#/Java), поскольку в этом случае подклассы даже не существуют до их конструкторы вызываются... но здесь возникает эта проблема.
Итак, каков наилучший/правильный дизайн/практика, чтобы этого не произошло?
Редактировать:
Я не обязательно говорю, что мне нужны циклические ссылки, но дело в том, что и Kernel
, и FileManager
зависят друг от друга. Если у вас есть предложение, как решить эту проблему без использования циклических ссылок, это тоже здорово!