One way to define compound or custom types in D is to
define them through a struct
:
struct Person {
int age;
int height;
float ageXHeight;
}
struct
s are always constructed on the stack (unless created
with new
) and are copied by value in assignments or
as parameters to function calls.
auto p = Person(30, 180, 3.1415);
auto t = p; // copy
When a new object of a struct
type is created, its members can be initialized
in the order they are defined in the struct
. A custom constructor can be defined through
a this(...)
member function. If needed to avoid name conflicts, the current instance
can be explicitly accessed with this
:
struct Person {
this(int age, int height) {
this.age = age;
this.height = height;
this.ageXHeight = cast(float)age * height;
}
...
Person p(30, 180); // initialization
p = Person(30, 180); // assignment to new instance
A struct
might contain any number of member functions. These
are by default public
and accessible from the outside. They could
also be private
and thus only be callable by other
member functions of the same struct
, or other code in the same
module.
struct Person {
void doStuff() {
...
private void privateStuff() {
...
p.doStuff(); // call method doStuff
p.privateStuff(); // forbidden
If a member function is declared with const
, it won't be allowed
to modify any of its members. This is enforced by the compiler.
Making a member function const
makes it callable on any const
or immutable
object, but also guarantees to callers that
the member function will never change the state of the object.
If a member function is declared as static
, it will be callable
without an instantiated object (e.g. Person.myStatic()
) but it
isn't allowed to access any non-static
members. It can be used if a
method doesn't need to access any of the object member fields but logically
belongs to the same class. Also it can be used to provide some functionality
without creating an explicit instance, for example, some Singleton
design pattern implementations use static
.
Note that a struct
can't inherit from another struct
.
Hierachies of types can only be built using classes,
which we will see in a future section.
However, with alias this
or mixins
one can easily achieve
polymorphic inheritance.
Given the struct Vector3
, implement the following functions and make
the example application run successfully:
length()
- returns the vector's length
dot(Vector3)
- returns the dot product of two vectors
toString()
- returns a string representation of this vector.
The function std.string.format
returns a string using printf
-like syntax:
format("MyInt = %d", myInt)
. Strings will be explained in detail in a later
section.