Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Сравнения

Эти трейты поддерживают сравнение значений. Все трейты можно получить через derive для типов, содержащих поля, которые реализуют эти трейты.

PartialEq и Eq

PartialEq — частичное отношение эквивалентности с обязательным методом eq и предоставляемым методом ne. Операторы == и != вызывают эти методы.

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

struct Key {
    id: u32,
    metadata: Option<String>,
}
impl PartialEq for Key {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

Eq — полное отношение эквивалентности (рефлексивное, симметричное и транзитивное), и оно подразумевает PartialEq. Функции, которые требуют полной эквивалентности, используют Eq как ограничение трейта.

PartialOrd и Ord

PartialOrd задаёт частичный порядок с методом partial_cmp. Он используется для реализации операторов <, <=, >= и >.

// Copyright 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

use std::cmp::Ordering;
#[derive(Eq, PartialEq)]
struct Citation {
    author: String,
    year: u32,
}
impl PartialOrd for Citation {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match self.author.partial_cmp(&other.author) {
            Some(Ordering::Equal) => self.year.partial_cmp(&other.year),
            author_ord => author_ord,
        }
    }
}

Ord — полный порядок, где cmp возвращает Ordering.

This slide should take about 5 minutes.
  • PartialEq можно реализовать между разными типами, а Eq нельзя, потому что он рефлексивен:

    // Copyright 2023 Google LLC
    // SPDX-License-Identifier: Apache-2.0
    
    struct Key {
        id: u32,
        metadata: Option<String>,
    }
    impl PartialEq<u32> for Key {
        fn eq(&self, other: &u32) -> bool {
            self.id == *other
        }
    }
  • На практике эти трейты часто получают через derive, но реализуют их вручную редко.

  • При сравнении ссылок в Rust сравниваются значения того, на что они указывают, а НЕ сами ссылки. Поэтому ссылки на два разных объекта могут сравниваться как равные, если значения, на которые они указывают, одинаковы:

    // Copyright 2023 Google LLC
    // SPDX-License-Identifier: Apache-2.0
    
    fn main() {
        let a = "Hello";
        let b = String::from("Hello");
        assert_eq!(a, b);
    }