Programming in D for Java Programmers
Hello World
Assuming you've downloaded a D compiler, a basic "hello world" program will look like this:
1 // hello.d
2 import std.stdio;
3
4 void main(string[] args)
5 {
6 writeln("Hello, world!");
7 }
If you're using DMD, you can run dmd -run hello.d
to compile and execute the program.
There are two main differences from a "hello world" in Java. First, there is no need for a class
. In D, functions can exist at the top-level, inside a class
or struct
as a method, and even inside another function. The only requirement (without abusing features of D) is that the main
function is located at the top-level.
This isn't the only way to define main
; the following will work as well:
void main() {}
int main() { return 0; }
int main(string[] args) { return 0; }
Using void
as the return type means a successful run of the program exits with 0
[1].
Downcasting
The Java way
if (animal instanceof Cat)
{
Cat cat = (Cat) animal;
/* use cat */
}
The D way
if(auto cat = cast(Cat) animal)
{
/* use cat */
}
Static Class Member Variables
In Java if you declare a member variable as static
it will be stored in global storage for the entire program, allowing you to access the same reference from multiple threads.
1 class Person {
2 public String firstName;
3
4 public Person(String fname) {
5 this.firstName = fname;
6 }
7 }
8
9 class ProgramState {
10 public static Person person;
11
12 static {
13 person = new Person("Jessie");
14 }
15 }
16
17 public class Program {
18
19 public static void main(String[] args) throws Exception {
20 new ProgramState();
21 Thread secondThread = new Thread(new Runnable() {
22 @Override
23 public void run() {
24 ProgramState.person.firstName = "James";
25 }
26 });
27 System.out.println(ProgramState.person.firstName); // => Jessie
28 secondThread.start();
29 secondThread.join();
30 System.out.println(ProgramState.person.firstName); // => James
31 }
32 }
A static
member variable in D is local to the current thread only, known as thread-local storage. Every thread you create will have a different version of your static
member variables.
To have the same behaviour as Java in D, you need to use the __gshared
type qualifier.
1 import core.thread;
2
3 class Person
4 {
5 string firstName;
6
7 this(string fname) {
8 firstName = fname;
9 }
10 }
11
12 class ProgramState
13 {
14 __gshared static Person person;
15
16 static this()
17 {
18 person = new Person("Jessie");
19 }
20 }
21
22 void main()
23 {
24 new ProgramState();
25 Thread secondThread = new Thread(() {
26 ProgramState.person.firstName = "James";
27 });
28 assert("Jessie" == ProgramState.person.firstName);
29 secondThread.start();
30 secondThread.join();
31 assert("James" == ProgramState.person.firstName, "firstName is not James");
32 }
Removing the __gshared
from the above snippet will result in the second assertion failing as ProgramState.person.firstName
will be "Jessie"
.
For an overview of the different forms of concurrency, see the Data Sharing Concurrency chapter in Programming in D which also explains one of D's preferred way of sharing variables between threads: shared
.