(我将其标记为 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
。如果您有关于如何在不使用循环引用的情况下缓解此问题的建议,那也很棒!