В Rust отсутствует встроенная поддержка ООП, но вы все равно можете использовать эти методы, чтобы воспользоваться преимуществами этой парадигмы.

Объектно-ориентированное программирование (ООП) упрощает проектирование программного обеспечения, делая упор на использование объектов для представления сущностей и концепций реального мира. ООП поощряет ремонтопригодность, инкапсулируя функциональность в объекты.

Rust — гибкий язык, поддерживающий функциональное и процедурное программирование. Хотя он изначально не поддерживает объектно-ориентированное программирование, вы можете реализовать концепции ООП, используя встроенные типы данных Rust.

Инкапсуляция в Rust

Инкапсуляция влечет за собой организацию кода в автономные блоки, которые скрывают внутренние детали, в то время как предоставление общедоступного интерфейса для внешнего взаимодействия, чтобы минимизировать сложность и улучшить код ремонтопригодность.

Вы можете инкапсулировать код Rust с помощью модулей. Модуль — это набор элементов, включая функции, структуры, перечисления и константы. Модули Rust предоставляют функциональные возможности для группировки и определения границ между частями программы.

instagram viewer

Использование модулей для инкапсуляции данных и функций

Вы можете определить модуль, используя мод ключевое слово, за которым следует имя:

мод мой_модуль {
// элементы модуля идут сюда
}

Вы можете организовать модули иерархически, вложив их объявления:

мод родительский_модуль {
мод мой_модуль {
// элементы модуля идут сюда
}
}

Затем вы можете ссылаться на вложенные модули с полной иерархией, разделяя каждый модуль двойным двоеточием, например, parent_module:: мой_модуль.

По умолчанию элементы в модулях являются частными и доступны только для кода в том же модуле. Но вы можете сделать модули общедоступными, используя паб ключевое слово:

мод мой_модуль {
пабфнмоя_функция() {
// здесь находится тело функции
}
}

Затем вы можете получить доступ моя_функция из других частей вашей программы.

Использование признаков для определения поведения

Еще один способ, которым Rust обеспечивает инкапсуляцию, — это использование трейтов. Черты определяют поведение, которое типы могут реализовать, и обеспечивают соответствие разных типов одному и тому же интерфейсу.

пабчертадля печати {
фнРаспечатать(&себя);
}

пабструктураМой тип {
// поля структуры здесь
}

импл для печати для Мой тип {
фнРаспечатать(&себя) {
// реализация здесь
}
}

для печати черта имеет Распечатать метод, и Мой тип структура реализует для печати черта путем реализации Распечатать метод.

Используя трейты, вы можете гарантировать, что любой тип, реализующий для печати черта имеет Распечатать метод. Это удобно при работе с универсальным кодом, который должен взаимодействовать с различными типами, имеющими общее поведение.

Наследование в Rust

Наследование позволяет определить один класс на основе другого.. Подкласс унаследует свойства и методы своего родителя.

В Rust рекомендуется использовать композицию вместо наследования. Композиция – это процесс создания новых объектов путем объединения существующих. Вместо создания нового класса, наследующего функциональные возможности базового класса, вы можете создать новую структуру, содержащую экземпляр базовой структуры и ее поля.

Создание новых типов путем объединения существующих типов

Вы будете использовать перечисления и структуры для создания новых типов. Перечисления удобны для типов с конечными значениями, а структуры могут содержать несколько полей.

Вы можете создать тип enum для разных видов животных.

перечислениеЖивотное {
Кот,
Собака,
Птица,
// ...
}

Кроме того, вы можете создать структуру, содержащую поля для каждого типа животных. Структуры могут содержать перечисления и другие типы.

структураЖивотное {
имя: Нить,
возраст: U8,
тип_животного: тип животного,
}

перечислениеТип животных {
Кот,
Собака,
Птица,
// ...
}

Животное структура содержит значения Тип животных тип перечисления.

Вы можете использовать трейты для реализации наследования и добавления поведения к типу без создания нового.

чертаЛетать {
фнлетать(&себя);
}

Вот как можно реализовать Летать черта для нескольких типов.

структураПтица {
имя: Нить,
размах крыльев: ф32,
}

импл Летать для Птица {
фнлетать(&себя) {
распечатать!("{} летает!", себя.имя);
}
}

структураСамолет {
модель: Нить,
максимальная скорость: U32,
}

импл Летать для Самолет {
фнлетать(&себя) {
распечатать!("{} летает!", себя.модель);
}
}

Птица и Самолет структуры реализуют Летать черта и вывести строки с Распечатать! макрос.

Вы можете позвонить в летать для обеих структур, не зная их конкретных типов.

фносновной() {
позволять птица = птица {
имя: Нить::от("Орел"),
размах крыльев: 2.0,
};

позволять плоскость = плоскость {
модель: Нить::от("Боинг 747"),
максимальная скорость: 900,
};

позволять летающие_объекты: Векдин Летать> = век![&птица, &самолет];

для объект в летающие_объекты {
объект.летать();
}
}

основной функция создает экземпляр Самолет и Птица типы. летающие_объекты вектор — это вектор экземпляров объекта, а для цикл проходит через вектор и вызывает летать метод на экземплярах.

Реализация полиморфизма в Rust

Класс или тип полиморфный, если несколько типов представляют интерфейс. Поскольку трейты предоставляют функциональность для определения поведения в Rust, предоставляя при этом общий интерфейс для написания универсального кода, вы можете использовать трейты для реализации полиморфизма.

Вот черта с названием Drawable который определяет поведение для рендеринга объектов на экране:

чертаDrawable {
фнрисовать(&себя);
}

Типы, реализующие трейт Drawable, могут получить доступ к рисовать функция.

структураПрямоугольник {
ширина: U32,
высота: U32,
}

импл Drawable для Прямоугольник {
фнрисовать(&себя) {
// Отрисовываем прямоугольник на экране
}
}

Вы можете написать общий код, рисующий объекты, реализующие Drawable черта.

фнdraw_object(объект: &T) {
объект.рисовать();
}

draw_object функция принимает общий тип Т в качестве входных данных, реализующих Drawable черта и называет рисовать метод на черте. Различные объекты могут реализовывать Drawable черта и получить доступ к функциональности.

Реализация абстракции в Rust

Абстракция — это концепция ООП где классы и интерфейсы доступны для указанных объектов и типов. Вы можете реализовать абстракцию в Rust с помощью трейтов.

Вот пример трейта для медиаплеера:

чертаСМИ {
фниграть(&себя);
}

Структуры и перечисления, реализующие СМИ трейт должен обеспечивать реализацию играть метод.

структураПесня {
заголовок: Нить,
художник: Нить,
}

импл СМИ для Песня {
фниграть(&себя) {
распечатать!("Воспроизведение песни: {} от {}", себя.заголовок, себя.художник);
}
}

Песня структура реализует СМИ черта, предоставляя реализацию для играть метод, который печатает сообщение с полями Песня структуры в консоль.

фносновной() {
// Создаем экземпляр структуры Song
позволять песня = песня {
заголовок: Нить::от("Богемская рапсодия"),
художник: Нить::от("Королева"),
};

// Вызываем метод play для экземпляра песни
песня.играть();
}

песня переменная является экземпляром Песня struct, и переменная может получить доступ и вызвать играть метод.

Организовать код Rust легко

Объектно-ориентированное программирование помогает в организации кода. Благодаря модульной системе Rust вы можете легко организовать свой код Rust, реализуя концепции ООП для своего приложения, чтобы ваш код был организованным, управляемым и интуитивно понятным.