Una forma de definir tipos de datos compuestos o personalizados en D es
definirlos a través de una estructura mediante la palabra reservada struct
.
struct Person {
int age;
int height;
float ageXHeight;
}
Las struct
s son siempre construidas en la pila (stack, en inglés; a no ser
que sean creadas mediante new
) y son siempre copiadas por valor en
asignaciones o como parámetros en llamadas a funciones.
auto p = Person(30, 180, 3.1415);
auto t = p; // copy
Cuando un nuevo objeto de tipo struct
se crea, todos sus miembros pueden ser
inicializados en el orden en que están definidos en dicha struct
. Se puede
definir un constructor predeterminado a través del método this(...)
. Si se
necesita evitar conflictos con los nombres de los parámetros, la instancia
actual de la estructura puede ser accedida mediante this
.
struct Person {
this(int age, int height) {
this.age = age;
this.height = height;
this.ageXHeight = cast(float)age * height;
}
...
Person p = Person(30, 180); // inicialización
p = Person(30, 180); // asignación a una nueva instancia
Una struct
puede contener cualquier número de funciones miembro. Estos
métodos son públicos (public
) de forma predeterminada y accesibles desde
cualquier sitio. Estos métodos podrían declararse como privados (private
)
y sólo podría acceder a ellos otro método de la struct
o código dentro
del mismo módulo.
struct Person {
void doStuff() {
...
private void privateStuff() {
...
p.doStuff(); // llamada al método doStuff
p.privateStuff(); // prohibido
Si una función miembro es declarada usando const
, no está permitido que
dicha función modifique ninguno de sus miembros. Esto lo fuerza el compilador.
Hacer una función miembro const
hace que sólo se pueda llamar desde cualquier
objeto const
o immutable
; además se garantiza que los objetos que llaman a
dicha función nunca cambiarán el estado del objeto.
Si una función miembro se declara como static
, esta se podrá llamar sin
la necesidad de instanciar ningún objeto (por ejemplo: Person.myStatic()
),
pero no está permitido acceder a miembros que no estén marcados como static
.
Esto se puede usar cuando un método no necesita acceder a ningún miembro del
objeto pero que, evidentemente, pertenece a la misma clase. Además, esto se
puede usar para proporcionar funcionalidad sin tener que crear una instancia.
Por ejemplo, algunos patrones Singleton utilizan static
para su
implementación.
Hay que tener en cuenta que una estructura no puede heredar de otras estructuras.
Las herencias entre tipos sólo se pueden construir usando clases, que se verán
en una sección futura. Sin embargo, mediante las sentencia alias this
y/o
mixins
fácilmente se puede conseguir herencia polimórfica.
Dada la estructura struct Vector3
, implementa las siguientes funciones y haz
que la aplicación de ejemplo se ejecute correctamente:
length()
: devuelve la longitud del vector.
dot(Vector3)
: devuelve el producto de dos vectores.
toString()
: devuelve una cadena representando este vector.
La función std.string.format
devuelve una cadena usando una sintaxis similar a la de printf
:
format("MyInt = %d", myInt)
. Las cadenas de caracteres (strings en inglés)
serán explicadas con más detalles en próximas secciones.