On 2010-11-11 13:10, Per Ångström wrote:
I hope we can all agree that minimizing module interdependencies is a good thing, that a highly interdependent set of modules is generally harder to understand and more difficult to test than if the module-dependency chain is acyclic.With that in mind, suppose I have the following C++ code, organized with a separation of interface and implementation, with no circular include dependencies: // IStudent.h class ITeacher; // forward reference class IStudent { public: virtual void ask(ITeacher &) = 0; virtual void learn(ITeacher &, const char * knowledge) = 0; }; // ITeacher.h class IStudent; // forward reference class ITeacher { public: virtual void teach(IStudent &) = 0; }; // Student.h #include "IStudent.h" class Student : public IStudent { public: void ask(ITeacher &); void learn(ITeacher &, const char * knowledge); }; // Teacher.h #include "ITeacher.h" class Teacher: public ITeacher { public: void teach(IStudent &); }; // Student.cpp #include "Student.h" #include "ITeacher.h" void Student::ask(ITeacher & teacher) { teacher.teach(*this); } void Student::learn(ITeacher &, const char * ) { } // Teacher.cpp #include "Teacher.h" #include "IStudent.h" void Teacher::teach(IStudent & student) { student.learn(*this, "knowledge"); } // main.cpp #include "Student.h" #include "Teacher.h" int main() { Student student; Teacher teacher; student.ask(teacher); return 0; } Below is my attempt at porting the code to D2. I hope I'm missing something due to my limited experience with D, but it seems D forces me to create circular dependencies between modules ITeacher and IStudent, since I cannot find a way to forward-declare types external to the current module in D like in C/C++. // IStudent.d import ITeacher; // would like to forward-declare the interface instead interface IStudent { void ask(ITeacher); void learn(ITeacher, string knowledge); } // ITeacher.d import IStudent; interface ITeacher { void teach(IStudent); } // Student.d import IStudent; class Student : IStudent { void ask(ITeacher teacher) { teacher.teach(this); } void learn(ITeacher teacher, string knowledge) { } } // Teacher.d import ITeacher; import IStudent; class Teacher: ITeacher { void teach(IStudent student) { student.learn(this, "knowledge"); } } // main.d import Student; import Teacher; void main() { auto student = new Student; auto teacher = new Teacher; student.ask(teacher); } So my question is: Am I missing something, or is this the D way to do it? Cheers,
First you have to import ITeacher in Student.d (if I'm reading this right). Second, D has (generally) no problems with circular references. You only get problems when two modules is a part of a circular reference and both have module constructors. If you porting C++ code you will not have this problem since C++ doesn't have module constructors.
BTW, you generally don't separate your interface and implementation in D (you can to that if you want to hide your implementation).
The import/module system in D is more like the one in Java than the one in C/C++.
-- /Jacob Carlborg
