Одним із способів визначення складених або спеціалізованих типів у D є
визначення їх через struct:
struct Person {
int age;
int height;
float ageXHeight;
}
Структури завжди створюються у стеці (якщо не створенi за допомогою new)
і копіюються за значенням при присвоєнні чи при передачі у якості
параметру фукнції.
auto p = Person(30, 180, 3.1415);
auto t = p; // створюється копія
Коли створюється новий об'єкт типу struct, його члени можуть бути
ініціалізовані у тому ж порядку, в якому вони визначені у struct.
Користувач сам може визначити конструктор за допомогою ключового слова
this(...). Щоб уникнути конфлікту імен, поточний екземпляр структури
може бути явно доступний за допомогою ключового слова this:
struct Person {
this(int age, int height) {
this.age = age;
this.height = height;
this.ageXHeight = cast(float)age * height;
}
...
Person p(30, 180); // iнiцiалiзацiя
p = Person(30, 180); // призначення новим екземпляром
struct може містити будь-яку кількість функцій. За замовчуванням усi
вони мають рiвень захисту public і доступнi ззовні. Вони можуть також
мати рiвень захисту private. У цьому випадку їх зможуть викликати
лише функції тієї ж структури, або інши код того ж самого модуля.
struct Person {
void doStuff() {
...
private void privateStuff() {
...
p.doStuff(); // викликає метод doStuff
p.privateStuff(); // заборонено
Якщо функція оголошується з ключовим словом const, то буде заборонено
змінювати будь-який її член. Це забезпечується компілятором. Функція з
ключовим словом const може бути викликаною з будь-якого const або
immutable об'єкта, і є гарантія, що ця функція не змінить стан об'єкта.
Якщо функція оголошена як static, вона буде викликатися без екземпляра
об'єкта (наприклад - Person.myStatic()), але їй заборонений доступ до
будь-яких не-static членів. static функцію можна використовувати,
якщо вам не потрібний доступ до полів об'єкту, але логічно його
розмістити у тому ж класі. Також можна використовувати статичні функції
для реалізації функціональності, якій не потрібно створювати об'єкт.
Наприклад, шаблон проектування Сінглтон (або Singleton, який існує
лише в одному екземплярi) використовує static.
Зверніть увагу, що struct не може успадковуватись від іншого struct.
Iєрархiї типів можуть бути побудовані тільки з використанням класів,
з якими ми ознайомимось у наступному розділі. Однак з alias this
або mixins можна легко досягти поліморфного успадкування.
Маючи struct Vector3 реалізувати наступні функції і зробити
так, щоб приклад програми виконувався успішно:
length() - повертає довжину вектора.
dot(Vector3) - повертає скалярний добуток двох векторiв.
toString() - повертає рядкове уявлення вектору.
Функцiя std.string.format
повертає рядок використовуючи printf-подiбний синтаксис:
format("MyInt = %d", myInt). Більш детально рядки будуть пояснені у
наступих розділах.