Руководство разработчика Node.js о Rust
В нашей предыдущей статье мы обсуждали мощную систему типов Rust с точки зрения разработчика Node.js. Вы можете найти статью здесь:
Опираясь на нашу предыдущую статью, в которой была представлена мощная система типов Rust, в этой статье мы углубимся в основные функции Rust: структуры, свойства, перечисления и коллекции, с примерами и сравнениями с Node.js.
Структуры
В Rust структуры — это настраиваемые типы данных, которые позволяют вам группировать связанные фрагменты данных. Они похожи на объекты JavaScript с точки зрения функциональности, но имеют другой синтаксис.
Пример структуры Rust:
struct User { username: String, email: String, sign_in_count: u64, active: bool, } fn main() { let user1 = User { email: String::from("user@example.com"), username: String::from("username123"), active: true, sign_in_count: 1, }; }
Пример объекта Node.js:
class User { constructor(email, username, active, signInCount) { this.email = email; this.username = username; this.active = active; this.signInCount = signInCount; } } const user1 = new User("user@example.com", "username123", true, 1);
В примере на Rust мы определяем структуру User
с полями и их соответствующими типами. В основной функции мы создаем экземпляр структуры User
, предоставляя значения для каждого поля. В примере Node.js мы определяем класс User
с помощью конструктора и создаем экземпляр, используя ключевое слово new
.
Черты
Трейты в Rust похожи на интерфейсы в других языках, что позволяет вам определять общее поведение для разных типов. Они полезны для реализации полиморфизма, и их можно сравнить с наследованием на основе прототипов в JavaScript.
Пример признака ржавчины:
trait Speak { fn speak(&self); } struct Human { name: String, } struct Dog { name: String, } impl Speak for Human { fn speak(&self) { println!("Hello, my name is {}.", self.name); } } impl Speak for Dog { fn speak(&self) { println!("Woof! My name is {}.", self.name); } } fn main() { let human = Human { name: String::from("Alice") }; let dog = Dog { name: String::from("Buddy") }; human.speak(); dog.speak(); }
Пример интерфейса Node.js:
class Speakable { speak() { throw new Error("speak method not implemented"); } } class Human extends Speakable { constructor(name) { super(); this.name = name; } speak() { console.log(`Hello, my name is ${this.name}.`); } } class Dog extends Speakable { constructor(name) { super(); this.name = name; } speak() { console.log(`Woof! My name is ${this.name}.`); } } const human = new Human("Alice"); const dog = new Dog("Buddy"); human.speak(); dog.speak();
В примере Rust мы определяем трейт Speak
с помощью одного метода speak
. Затем мы определяем две структуры, Human
и Dog
, и реализуем трейт Speak
для каждой из них. В примере Node.js мы достигаем аналогичного результата, используя наследование классов.
перечисления
Перечисления в Rust позволяют определить тип, который может представлять один из нескольких вариантов. Это полезно для создания структур данных, которые могут содержать различные типы данных. В JavaScript вы можете достичь аналогичной функциональности, используя помеченные объединения или размеченные объединения.
Пример перечисления в Rust:
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } fn process_message(message: Message) { match message { Message::Quit => println!("Quit"), Message::Move { x, y } => println!("Move to x: {}, y: {}", x, y), Message::Write(text) => println!("Write: {}", text), Message::ChangeColor(r, g, b) => println!("Change color to red: {}, green: {}, blue: {}", r, g, b), } } fn main() { let message = Message::Write(String::from("Hello, Rust!")); process_message(message); }
Пример размеченного объединения Node.js:
class Message { constructor(type) { this.type = type; } } class Quit extends Message { constructor() { super("Quit"); } } class Move extends Message { constructor(x, y) { super("Move"); this.x = x; this.y = y; } } class Write extends Message { constructor(text) { super("Write"); this.text = text; } } class ChangeColor extends Message { constructor(r, g, b) { super("ChangeColor"); this.r = r; this.g = g; this.b = b; } } function processMessage(message) { switch (message.type) { case "Quit": console.log("Quit"); break; case "Move": console.log(`Move to x: ${message.x}, y: ${message.y}`); break; case "Write": console.log(`Write: ${message.text}`); break; case "ChangeColor": console.log(`Change color to red: ${message.r}, green: ${message.g}, blue: ${message.b}`); break; } } const message = new Write("Hello, Node.js!"); processMessage(message);
В примере Rust мы определяем enum Message
с четырьмя вариантами, каждый из которых представляет различный тип сообщения. Затем мы создаем функцию process_message
, которая использует сопоставление с образцом для обработки каждого варианта. В примере Node.js мы используем базовый класс Message
и создаем подклассы для каждого варианта, используя свойство type
для функциональности размеченного объединения.
Коллекции
Rust предлагает несколько встроенных типов коллекций для хранения и организации данных, таких как Vec
(растущий массив), HashMap
(хранилище ключ-значение) и HashSet
(набор уникальных значений). В Node.js вы можете использовать собственные структуры данных, такие как Array
, Map
и Set
, для аналогичных целей.
Пример коллекций Rust:
use std::collections::{HashMap, HashSet}; fn main() { let mut vec = Vec::new(); vec.push(1); vec.push(2); vec.push(3); let mut hashmap = HashMap::new(); hashmap.insert(String::from("Blue"), 10); hashmap.insert(String::from("Yellow"), 20); let mut hashset = HashSet::new(); hashset.insert(1); hashset.insert(2); hashset.insert(3); }
Пример коллекций Node.js:
const array = [1, 2, 3]; const map = new Map(); map.set("Blue", 10); map.set("Yellow", 20); const set = new Set([1, 2, 3]);
В примере Rust мы импортируем и создаем Vec
, HashMap
и HashSet
из стандартной библиотеки. После этого мы вставляем значения в каждую из этих коллекций. Между тем, пример Node.js демонстрирует, как добиться аналогичной функциональности, используя собственные структуры данных, такие как Array
, Map
и Set
.
Заключение
На протяжении всей этой статьи мы исследовали некоторые важные функции Rust, включая структуры, трейты, перечисления и коллекции, проводя сравнения с концепциями Node.js. Нашей целью было дать вам более глубокое понимание внутренней работы Rust и того, как вы можете эффективно использовать его возможности. Как разработчик Node.js, изучение Rust может расширить ваш кругозор, улучшить навыки решения проблем, повысить производительность и позволить вам писать более безопасный и параллельный код. Удачного кодирования!