Руководство разработчика 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("[email protected]"),
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("[email protected]", "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 может расширить ваш кругозор, улучшить навыки решения проблем, повысить производительность и позволить вам писать более безопасный и параллельный код. Удачного кодирования!