Uma maneira de definir tipos compostos ou personalizados em D é
usar um struct:
struct Person {
int age;
int height;
float ageXHeight;
}
Por padrão, os structs são construídos na pilha (a menos que sejam criados
com new) e são copiados por valor em atribuições ou
como parâmetros para chamadas de função.
auto p = Person(30, 180, 3.1415);
auto t = p; // cópia
Quando um novo objeto de um tipo struct é criado, seus membros podem ser inicializados
na ordem em que são definidos no struct. Um construtor personalizado pode ser definido por meio de
uma função membro chamado this(...). Se necessário, para evitar conflitos de nomes, a instância atual
pode ser acessada explicitamente com 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); // inicialização
p = Person(30, 180); // atribuiu nova instância
Um struct pode conter qualquer número de funções-membro. Por padrão
elas são public e acessíveis do lado de fora. Elas podem
também podem ser private e, portanto, só podem ser chamadas por outras
funções-membro do mesmo struct, ou outro código no mesmo
módulo.
struct Person {
void doStuff() {
...
private void privateStuff() {
...
// Em outro módulo:
p.doStuff(); // chamando o método doStuff
p.privateStuff(); // proibido
constSe uma função membro for declarada com const, não será permitido
modificar nenhum de seus membros. Isso é imposto pelo compilador.
Tornar uma função membro const faz com que ela possa ser chamada em qualquer objeto const
ou objeto immutable, mas também garante aos chamadores que
a função de membro nunca alterará o estado do objeto.
staticSe uma função membro for declarada como static, ela poderá ser chamada
sem um objeto instanciado (por exemplo, Person.myStatic()), mas ela
não poderá acessar nenhum membro que não seja static. Ele pode ser usado se um método
não precisar acessar nenhum dos campos de membro do objeto, mas logicamente
pertence à mesma classe. Também pode ser usado para fornecer alguma funcionalidade
sem criar uma instância explícita, por exemplo, algumas implementações do padrão de design Singleton
usam static.
Observe que um struct não pode herdar de outro struct.
As hierarquias de tipos só podem ser construídas usando classes,
que veremos em uma seção posterior.
Entretanto, com alias this ou mixins é possível obter facilmente
herança polimórfica.
Dado o struct Vector3, implemente as seguintes funções e faça com que
o aplicativo de exemplo seja executado com êxito:
length() - retorna o tamanho do vetor
dot(Vector3) - retorna o ponto do produto de dois vetores
toString() - retorna uma representação de string desse vetor.
A função std.string.format
retorna uma string usando a sintáxe parecido com printf:
format("MyInt = %d", myInt). As strings serão explicadas em detalhes em uma
seção posterior.