Menu
CoddyTech

Снова об Option Enum

Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 17 из 61.

Ты уже сталкивался с Option<T> в Rust: это стандартное перечисление для представления значений, которые могут существовать или не существовать. Теперь посмотрим на него с точки зрения ООП: Option — это не просто перечисление, а тип с мощными встроенными методами, которые позволяют безопасно и элегантно обрабатывать nullable-значения.

Вместо того чтобы каждый раз сопоставлять варианты, можно использовать методы непосредственно для значений Option. Метод unwrap_or возвращает внутреннее значение, если оно есть, или значение по умолчанию, которое ты укажешь:

let maybe_name: Option<String> = Some(String::from("Alice"));
let name = maybe_name.unwrap_or(String::from("Guest"));
println!("{}", name);  // Alice

let empty: Option<String> = None;
let fallback = empty.unwrap_or(String::from("Guest"));
println!("{}", fallback);  // Guest

Метод map преобразует внутреннее значение, если оно есть, а None оставляет без изменений. Это позволяет объединять операции в цепочку, не проверяя постоянно наличие None:

let maybe_num: Option<i32> = Some(5);
let doubled = maybe_num.map(|x| x * 2);
println!("{:?}", doubled);  // Some(10)

let nothing: Option<i32> = None;
let still_nothing = nothing.map(|x| x * 2);
println!("{:?}", still_nothing);  // None

Эти методы воплощают принципы ООП: тип Option инкапсулирует понятие «возможно, значение есть» и предоставляет удобный интерфейс для работы с ним. Ты вызываешь методы объекта, а не пишешь внешнюю логику для его проверки.

challenge icon

Задание

Легко

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

Для организации кода создадим два файла:

  • profile.rs: Определи публичную структуру Profile с двумя полями: username (String) и nickname (Option<String>). Реализуй:
    • Конструктор new, который принимает имя пользователя и опциональный никнейм
    • Метод display_name, который возвращает никнейм, если он есть, или имя пользователя в качестве значения по умолчанию: используй unwrap_or для этого
    • Метод formatted_nickname, который возвращает Option<String> с никнеймом в квадратных скобках (например, "[CoolNick]"), если он есть, или None, если никнейма нет: используй map, чтобы преобразовать значение
  • main.rs: Подключи модуль профиля и создай два профиля: один с никнеймом, другой без него. Продемонстрируй работу обоих методов для каждого профиля, чтобы показать, как методы Option по-разному обрабатывают имеющиеся и отсутствующие значения.

Для метода formatted_nickname при выводе используй отладочное форматирование ({:?}), поскольку он возвращает Option.

Вывод должен соответствовать этому точному формату и содержать оба профиля:

Display name: {name}
Formatted nickname: {option}
Display name: {name}
Formatted nickname: {option}

Например, для профиля с именем пользователя "alice" и никнеймом "Ace", а также профиля с именем пользователя "bob" без никнейма вывод будет таким:

Display name: Ace
Formatted nickname: Some("[Ace]")
Display name: bob
Formatted nickname: None

Ты получишь три входных значения: имя первого пользователя, никнейм первого пользователя и имя второго пользователя (у которого нет никнейма).

Попробуйте сами

mod profile;

use profile::Profile;

fn main() {
    // Считайте входные данные
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let username1 = input1.trim().to_string();

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let nickname1 = input2.trim().to_string();

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let username2 = input3.trim().to_string();

    // TODO: Создайте первый профиль с username1 и nickname1 (Some)
    
    // TODO: Создайте второй профиль с username2 без псевдонима (None)
    
    // TODO: Выведите display_name и formatted_nickname для первого профиля
    // Используйте {:?} для formatted_nickname, поскольку он возвращает Option
    
    // TODO: Выведите display_name и formatted_nickname для второго профиля
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Rust