Reputation: 2619
I come from Java backgrounds and the problem of packaging is as follows then:
I can have many files under the same package, say com.parobay.io
. I can then distribute this as a library, and the users will use it like this:
import com.parobay.io.Input;
import com.parobay.io.Output;
or
import com.parobay.io.*; // to import everything
So I can have a single "module (com.parobay.io
) and classes defined in multiple files.
So how to I achieve the same in D? Do I have to create a directory com\parobay\io
and there place two files called Input.d
and Output.d
or is there a smarter way?
In Java the rules are very strict, so it's hard to get it wrong. In D there are many possibilities. So are there any conventions, like one class per file, or file name equal to the name of class?
Upvotes: 7
Views: 898
Reputation: 19797
D community has three widely accepted alternatives.
Write a module named all.d
which includes all modules from your package. (Literally '*' --> 'all'). After that you simply do import com.paroboy.io.all;
I see more and more that D developers use _
for this. So they write a module called _.d
for this purpose. Similarly to #1, you do import com.paroboy.io._;
Relatively new addition to the D programming language is the package.d
module, which can be used to import the package. More about this at the following DIP: http://wiki.dlang.org/DIP37 . If I remember well, DMD supports it since v2.064 . (Documentation: http://dlang.org/module#PackageModule)
I myself use the #1 approach because it is obvious what is going on. While #2 and #3 may be confusing to people reading D source file, especially the third one. A valid question someone may ask: "What the heck am I importing, package?? But import
is only for modules!??"
Allthough nothing stops you from having separate module per-class, I would not recommend it. D is truly modular language, so take advantage of that. Group all your types in a single D module. That is my advice, and that is the "D way".
NOTE: There is a (big) semantic difference between Java "module" and a D module, as you have probably already noticed. I am primarily a Java programmer, so I know how confusing this may be to Java programmers who are playing with D. Java classes in the same package quite often take advantage of the package-level access. However, classes within the same module behave like "friends" in C++.
Speaking about Java modules, they were supposed to come with Java 8 (true modules!), but were posponed and will hopefully be included in Java 9.
UPDATE: We reached conclusion, after a chat on FreeNode (IRC) with some members of the D-Programming-Language, that it is indeed safe now to use the package
attribute. It behaves as the specification says.
Upvotes: 2
Reputation: 25592
Don't use two separate files for your Input
and Output
classes. Instead, put both classes in a single file, parobay/io.d
(corresponding to the module parobay.io
).
It's definitely not the convention to limit yourself to just one class per file. D modules are for grouping together code of related functionality. When someone does import parobay.io;
, they expect to get all of parobay.io
- classes, utility functions and whatever else is relevant. It's similar to Java's import com.parobay.io.*;
.
If someone really wants to import specific parts of your module, they can use selective imports:
import parobay.io: Input; // Just the Input class of the parobay.io module.
import parobay.io: Output; // Just the Output class.
import parobay.io: Input, Output; // Just the Input and Output classes.
There are a few additional things to note about this.
foo.bar.baz
should be in the file foo/bar/baz.d
.com
or org
or net
if you really want to, but it's not expected like it is in Java.Adam D. Ruppe's answer has some great points about explicit module declarations and class member visibility. It's also well worth reading the module and style pages on the official D website.
Upvotes: 3
Reputation: 25605
You can choose to do it basically the same as Java, though remember these items:
import foo.*
doesn't work in D, but you CAN make a file called package.d
in the directory which manually lists public import foo.Input; public import foo.Output;
etc. which allows you to import the whole package.
ALWAYS put a module com.parobay.io.Input;
or whatever line at the top of any file that is imported. Don't expect it to just work based on directory structure and filename. The directory structure actually isn't strictly necessary, it is just a convention to easily find the file. The module
line at the top with the name is the authoritative thing the compiler checks.
D modules often have all lowercase names, but you can use uppercase ones if you like. I think it is nice to use a lowercase name like the class name, so you might call the module io.input
and the class Input
. The reason for this convention is sometimes filename case gets lost when transferring from system to system. But developers are pretty aware of case so in practice either way should work.
One class per file will work fine or you can put two tightly coupled classes together in the same file (they'll have access to each other's private members if they are in the same file).
See this page for more info: http://dlang.org/module especially search for the heading "Package Module"
Upvotes: 8