Difference between revisions of "Programming in D for Java Programmers"
(Downcasting) |
(Hello world example) |
||
(3 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
+ | == Hello World == | ||
+ | |||
+ | Assuming you've [https://dlang.org/download.html downloaded a D compiler], a basic "hello world" program will look like this: | ||
+ | |||
+ | <syntaxhighlight lang="D" line>// hello.d | ||
+ | import std.stdio; | ||
+ | |||
+ | void main(string[] args) | ||
+ | { | ||
+ | writeln("Hello, world!"); | ||
+ | }</syntaxhighlight> | ||
+ | |||
+ | If you're using [[DMD]], you can run <code>dmd -run hello.d</code> to compile and execute the program. | ||
+ | |||
+ | There are two main differences from a [https://en.wikipedia.org/wiki/Java_(programming_language)#Hello_world_example "hello world" in Java]. First, there is no need for a <code>class</code>. In D, functions can exist at the top-level, inside a <code>class</code> or <code>struct</code> as a method, and even inside another function. The only requirement (without abusing features of D) is that the <code>main</code> function is located at the top-level. | ||
+ | |||
+ | This isn't the only way to define <code>main</code>; the following will work as well: | ||
+ | |||
+ | * <syntaxhighlight lang="D" inline>void main() {}</syntaxhighlight> | ||
+ | * <syntaxhighlight lang="D" inline>int main() { return 0; }</syntaxhighlight> | ||
+ | * <syntaxhighlight lang="D" inline>int main(string[] args) { return 0; }</syntaxhighlight> | ||
+ | |||
+ | Using <code>void</code> as the return type means a successful run of the program exits with <code>0</code><ref>https://dlang.org/spec/function.html#main</ref>. | ||
+ | |||
== Downcasting == | == Downcasting == | ||
The Java way | The Java way | ||
Line 12: | Line 36: | ||
/* use cat */ | /* use cat */ | ||
}</syntaxhighlight> | }</syntaxhighlight> | ||
+ | |||
+ | == Static Class Member Variables == | ||
+ | |||
+ | In Java if you declare a member variable as <code>static</code> it will be stored in global storage for the entire program, allowing you to access the same reference from multiple threads. | ||
+ | |||
+ | <syntaxhighlight lang="Java" line> | ||
+ | class Person { | ||
+ | public String firstName; | ||
+ | |||
+ | public Person(String fname) { | ||
+ | this.firstName = fname; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class ProgramState { | ||
+ | public static Person person; | ||
+ | |||
+ | static { | ||
+ | person = new Person("Jessie"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public class Program { | ||
+ | |||
+ | public static void main(String[] args) throws Exception { | ||
+ | new ProgramState(); | ||
+ | Thread secondThread = new Thread(new Runnable() { | ||
+ | @Override | ||
+ | public void run() { | ||
+ | ProgramState.person.firstName = "James"; | ||
+ | } | ||
+ | }); | ||
+ | System.out.println(ProgramState.person.firstName); // => Jessie | ||
+ | secondThread.start(); | ||
+ | secondThread.join(); | ||
+ | System.out.println(ProgramState.person.firstName); // => James | ||
+ | } | ||
+ | }</syntaxhighlight> | ||
+ | |||
+ | A <code>static</code> 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 <code>static</code> member variables. | ||
+ | To have the same behaviour as Java in D, you need to use the <code>__gshared</code> type qualifier. | ||
+ | |||
+ | <syntaxhighlight lang="D" line>import core.thread; | ||
+ | |||
+ | class Person | ||
+ | { | ||
+ | string firstName; | ||
+ | |||
+ | this(string fname) { | ||
+ | firstName = fname; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class ProgramState | ||
+ | { | ||
+ | __gshared static Person person; | ||
+ | |||
+ | static this() | ||
+ | { | ||
+ | person = new Person("Jessie"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | new ProgramState(); | ||
+ | Thread secondThread = new Thread(() { | ||
+ | ProgramState.person.firstName = "James"; | ||
+ | }); | ||
+ | assert("Jessie" == ProgramState.person.firstName); | ||
+ | secondThread.start(); | ||
+ | secondThread.join(); | ||
+ | assert("James" == ProgramState.person.firstName, "firstName is not James"); | ||
+ | }</syntaxhighlight> | ||
+ | |||
+ | Removing the <code>__gshared</code> from the above snippet will result in the second assertion failing as <code>ProgramState.person.firstName</code> will be <code>"Jessie"</code>. | ||
+ | |||
+ | For an overview of the different forms of concurrency, see the [https://ddili.org/ders/d.en/concurrency_shared.html Data Sharing Concurrency] chapter in ''Programming in D'' which also explains one of D's preferred way of sharing variables between threads: <code>shared</code>. | ||
+ | |||
+ | == References == | ||
+ | |||
+ | <references /> | ||
+ | |||
+ | [[Category:Languages versus D]] |
Latest revision as of 06:08, 27 August 2023
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
.