Programming in D for Java Programmers

From D Wiki
Revision as of 10:06, 26 August 2023 by Lagtrain (talk | contribs) (Difference between Java's static member variables and D's)
Jump to: navigation, search

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.

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
   }
}

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.

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");
}

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.