digitalmars.D - Interface file
- Jan Johansson (49/49) Sep 30 2015 Hello all,
- Adam D. Ruppe (41/44) Sep 30 2015 FYI there's no actual difference between .di files and .d files.
- Jan Johansson (14/58) Sep 30 2015 Thanks,
- Steven Schveighoffer (25/35) Sep 30 2015 There is no reason to use interfaces here, you can separate declaration
- Jan Johansson (7/33) Sep 30 2015 Thanks Steve,
- Andrei Alexandrescu (3/3) Sep 30 2015 On 09/30/2015 02:01 PM, Adam D. Ruppe wrote:
- Jeremy DeHaan (43/92) Sep 30 2015 Like Adam said, the real difference between a .d and a .di file
- Jan Johansson (12/56) Sep 30 2015 Thanks Jeremy,
- Jeremy DeHaan (10/20) Oct 01 2015 Having the declarations in both files is the point though.
- Atila Neves (4/16) Oct 02 2015 The linker will be the bottleneck anyway, I don't think .di files
- Jan Johansson (48/97) Sep 30 2015 Hi again,
Hello all, I'm testing D language, and the first thing I want to do is to separate declaration from implementation. I was happy to find support of interfaces in the D language, and set out to do a basic test. However, this test failed, and I want some newbie help to understand how it should be done in D language. ---------------------- The interface file (I called it test.di): // Interface interface IMyTest { void Write(string message); } // Factory for type implementing IMyTest IMyTest createInstance(); ---------------------- The library file (I called it test.d): import std.stdio; class MyTest : IMyTest { void Write(string message) { writeln(message); } } IMyTest createInstance() { return new MyTest; } ---------------------- And finally the main file (I called it main.d): import test; import std.stdio; void main() { auto p = createInstance(); p.Write("Hello, World!"); } ---------------------- The assumption was that I could do: dmd test.d test.di -lib -oftest and next do: dmd main.d test.di test.a The shared information is in the test.di file. However, this failed, since the first statement generates the following: dmd test.d test.di -lib -oftest Error: module test from file test.di conflicts with another module test from file test.d I guess it is because the file name test.d and test.di creates conflict, surfaced as module test. How can I accomplish what I want to do? Kind regards, Jan Johansson
Sep 30 2015
On Wednesday, 30 September 2015 at 17:51:50 UTC, Jan Johansson wrote:The interface file (I called it test.di):FYI there's no actual difference between .di files and .d files. The way D is meant to be used is you write the declarations together, then if you want to, you can automatically strip the bodies out of a .d file (dmd -H does it) and that makes the .di file. But you always substitute the .di file for the .d file with the same name. They cannot be used together like a .h and .cpp file. You can put an interface in a separate module than a class. Then you import the interface module from both locations, though your factory function won't work like that. Try something like: itest.d: module itest; interface IMyTest { void Write(string message); } test.d: public import itest; // import the interface definition too import std.stdio; private class MyTest : IMyTest { void Write(string message) { writeln(message); } } public IMyTest createInstance() { return new MyTest; } main.d: import test; import std.stdio; void main() { auto p = createInstance(); p.Write("Hello, World!"); } And that should work.dmd test.d test.di -lib -oftestwould be more like `dmd itest.d test.d -lib -oftest`dmd main.d test.di test.aand `dmd main.d itest.d test.a` Or you could just compile it all at once with `dmd main.d test.d itest.d`
Sep 30 2015
On Wednesday, 30 September 2015 at 18:01:57 UTC, Adam D. Ruppe wrote:On Wednesday, 30 September 2015 at 17:51:50 UTC, Jan Johansson wrote:Thanks, But (there is always a but) ;-) The main.d should rely on itest.d, not test.d, otherwise I do the declaration for the library itself, but the main.d includes the test.d - the implementation (not the declaration). If I change the 'dmd main.d test.d test.a' to 'dmd main.d itest.d test.a', then I got a new error: itest.d:(.text._Dmain+0x5): undefined reference to `_D5itest14createInstanceFZC5itest7IMyTest' The linker get confused about the separation of the declaration and implementation. Best regards Jan JohanssonThe interface file (I called it test.di):FYI there's no actual difference between .di files and .d files. The way D is meant to be used is you write the declarations together, then if you want to, you can automatically strip the bodies out of a .d file (dmd -H does it) and that makes the .di file. But you always substitute the .di file for the .d file with the same name. They cannot be used together like a .h and .cpp file. You can put an interface in a separate module than a class. Then you import the interface module from both locations, though your factory function won't work like that. Try something like: itest.d: module itest; interface IMyTest { void Write(string message); } test.d: public import itest; // import the interface definition too import std.stdio; private class MyTest : IMyTest { void Write(string message) { writeln(message); } } public IMyTest createInstance() { return new MyTest; } main.d: import test; import std.stdio; void main() { auto p = createInstance(); p.Write("Hello, World!"); } And that should work.dmd test.d test.di -lib -oftestwould be more like `dmd itest.d test.d -lib -oftest`dmd main.d test.di test.aand `dmd main.d itest.d test.a` Or you could just compile it all at once with `dmd main.d test.d itest.d`
Sep 30 2015
On 9/30/15 2:12 PM, Jan Johansson wrote:Thanks, But (there is always a but) ;-) The main.d should rely on itest.d, not test.d, otherwise I do the declaration for the library itself, but the main.d includes the test.d - the implementation (not the declaration). If I change the 'dmd main.d test.d test.a' to 'dmd main.d itest.d test.a', then I got a new error: itest.d:(.text._Dmain+0x5): undefined reference to `_D5itest14createInstanceFZC5itest7IMyTest' The linker get confused about the separation of the declaration and implementation.There is no reason to use interfaces here, you can separate declaration from implementation without them: test.di: module test; class MyTest { void Write(string message); } test.d: module test; class MyTest { void Write(string message) { writeln(message); } } main.d: import test; // will work even if only test.di is available import std.stdio; void main() { auto p = new MyTest; p.Write("Hello, World!"); } Interfaces are only necessary when you are unsure what concrete type you need until runtime. -Steve
Sep 30 2015
On Wednesday, 30 September 2015 at 19:17:41 UTC, Steven Schveighoffer wrote:On 9/30/15 2:12 PM, Jan Johansson wrote:Thanks Steve, Your last statement is exactly what I want to do! Using contract based design, and factories to instantiate types that implements the interface. //Jan[...]There is no reason to use interfaces here, you can separate declaration from implementation without them: test.di: module test; class MyTest { void Write(string message); } test.d: module test; class MyTest { void Write(string message) { writeln(message); } } main.d: import test; // will work even if only test.di is available import std.stdio; void main() { auto p = new MyTest; p.Write("Hello, World!"); } Interfaces are only necessary when you are unsure what concrete type you need until runtime. -Steve
Sep 30 2015
On 09/30/2015 02:01 PM, Adam D. Ruppe wrote: [snip] Good material for a Q&A section of TWiD. -- Andrei
Sep 30 2015
On Wednesday, 30 September 2015 at 17:51:50 UTC, Jan Johansson wrote:Hello all, I'm testing D language, and the first thing I want to do is to separate declaration from implementation. I was happy to find support of interfaces in the D language, and set out to do a basic test. However, this test failed, and I want some newbie help to understand how it should be done in D language. ---------------------- The interface file (I called it test.di): // Interface interface IMyTest { void Write(string message); } // Factory for type implementing IMyTest IMyTest createInstance(); ---------------------- The library file (I called it test.d): import std.stdio; class MyTest : IMyTest { void Write(string message) { writeln(message); } } IMyTest createInstance() { return new MyTest; } ---------------------- And finally the main file (I called it main.d): import test; import std.stdio; void main() { auto p = createInstance(); p.Write("Hello, World!"); } ---------------------- The assumption was that I could do: dmd test.d test.di -lib -oftest and next do: dmd main.d test.di test.a The shared information is in the test.di file. However, this failed, since the first statement generates the following: dmd test.d test.di -lib -oftest Error: module test from file test.di conflicts with another module test from file test.d I guess it is because the file name test.d and test.di creates conflict, surfaced as module test. How can I accomplish what I want to do? Kind regards, Jan JohanssonLike Adam said, the real difference between a .d and a .di file is that the .di file has all the guts removed and is just the declarations. If using a .di file is really what you want, you could try something like this? test.d: module test; interface IMyTest { void Write(string message); } IMyTest createInstance() { class MyTest : IMyTest { void Write(string message) { import std.stdio; writeln(message); } } return new MyTest; } --------------- test.di: module test; interface IMyTest { void Write(string message); } IMyTest createInstance(); --------------- main.d: import test; void main() { auto p = createInstance(); p.Write("Hello, World!"); } -------------- and then dmd test.d -lib -oftest and dmd main.d test.di test.a Also like Adam said, dmd can create these .di files for you so you don't have to! (This is untested, but should work/be close to working)
Sep 30 2015
On Wednesday, 30 September 2015 at 19:24:05 UTC, Jeremy DeHaan wrote:On Wednesday, 30 September 2015 at 17:51:50 UTC, Jan Johansson wrote:Thanks Jeremy, Do you spot a weakness in your proposed code snip? The declaration for interface is done in two separate files, both test.d and test.di. Scattered declarations has never been a good idea. I know that I can ask the DMD to do declaration files for me, but the use case for that is to speed up building of executable. But is it that the separation of declaration and implementation was never the intention in the design of D? //Jan[...]Like Adam said, the real difference between a .d and a .di file is that the .di file has all the guts removed and is just the declarations. If using a .di file is really what you want, you could try something like this? test.d: module test; interface IMyTest { void Write(string message); } IMyTest createInstance() { class MyTest : IMyTest { void Write(string message) { import std.stdio; writeln(message); } } return new MyTest; } --------------- test.di: module test; interface IMyTest { void Write(string message); } IMyTest createInstance(); --------------- main.d: import test; void main() { auto p = createInstance(); p.Write("Hello, World!"); } -------------- and then dmd test.d -lib -oftest and dmd main.d test.di test.a Also like Adam said, dmd can create these .di files for you so you don't have to! (This is untested, but should work/be close to working)
Sep 30 2015
On Thursday, 1 October 2015 at 01:41:22 UTC, Jan Johansson wrote:Thanks Jeremy, Do you spot a weakness in your proposed code snip? The declaration for interface is done in two separate files, both test.d and test.di. Scattered declarations has never been a good idea. I know that I can ask the DMD to do declaration files for me, but the use case for that is to speed up building of executable. But is it that the separation of declaration and implementation was never the intention in the design of D? //JanHaving the declarations in both files is the point though. If you notice, the only difference between my test.d and test.di files is that test.di is only the declarations. The speed increase for compiling happens because of this. You still need all declarations to be there when you build, or at least the ones you use. You build the library with test.d and then build using test.di when you use the library. You never use both test.d and test.di together. Double check my build commands.
Oct 01 2015
On Thursday, 1 October 2015 at 17:12:02 UTC, Jeremy DeHaan wrote:On Thursday, 1 October 2015 at 01:41:22 UTC, Jan Johansson wrote:The linker will be the bottleneck anyway, I don't think .di files are worth it. Atila[...]Having the declarations in both files is the point though. If you notice, the only difference between my test.d and test.di files is that test.di is only the declarations. The speed increase for compiling happens because of this. You still need all declarations to be there when you build, or at least the ones you use. You build the library with test.d and then build using test.di when you use the library. You never use both test.d and test.di together. Double check my build commands.
Oct 02 2015
On Wednesday, 30 September 2015 at 17:51:50 UTC, Jan Johansson wrote:Hello all, I'm testing D language, and the first thing I want to do is to separate declaration from implementation. I was happy to find support of interfaces in the D language, and set out to do a basic test. However, this test failed, and I want some newbie help to understand how it should be done in D language. ---------------------- The interface file (I called it test.di): // Interface interface IMyTest { void Write(string message); } // Factory for type implementing IMyTest IMyTest createInstance(); ---------------------- The library file (I called it test.d): import std.stdio; class MyTest : IMyTest { void Write(string message) { writeln(message); } } IMyTest createInstance() { return new MyTest; } ---------------------- And finally the main file (I called it main.d): import test; import std.stdio; void main() { auto p = createInstance(); p.Write("Hello, World!"); } ---------------------- The assumption was that I could do: dmd test.d test.di -lib -oftest and next do: dmd main.d test.di test.a The shared information is in the test.di file. However, this failed, since the first statement generates the following: dmd test.d test.di -lib -oftest Error: module test from file test.di conflicts with another module test from file test.d I guess it is because the file name test.d and test.di creates conflict, surfaced as module test. How can I accomplish what I want to do? Kind regards, Jan JohanssonHi again, Here is a re-worked example. Again, I want to use the factory pattern, and have created four files. --- test.d (interface): interface IMyTest { void Write(string message); } --- mytesting.d (one implementation of interface): import test; class MyTesting : IMyTest { void Write(string message) { import std.stdio; writeln("MyTesting: " ~ message); } } --- factory.d (factory): import test; import mytesting; IMyTest createInstance() { return new MyTesting; } --- main.d (program): import factory; import std.stdio; void main() { auto p = createInstance(); p.Write("Hello, World!"); } --- There are a number of ways to build the executable. I want to use binary linkage as much as possible (the next step is to do dynamically linkage - but here I need help - I'm still a newbie). First I build the component (class) artifact: dmd mytesting.d -lib -ofmytesting Next I build the factory artifact: dmd factory.d -lib -offactory And then I close the loop: dmd main.d test.d factory.a mytesting.a --- //Jan
Sep 30 2015