Is there a way to forward-declare interfaces to avoid module interdependencies?

Jacob Carlborg doob at me.com
Thu Nov 11 06:51:44 PST 2010


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


More information about the Digitalmars-d-learn mailing list