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

Per Ångström d-news at autark.se
Thu Nov 11 04:10:15 PST 2010


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,
-- 
Per Å.


More information about the Digitalmars-d-learn mailing list