Какую альтернативу подтипам выбирают авторы библиотек и почему? - PullRequest
0 голосов
/ 06 июня 2018

У меня есть два типа, A и B, которые имеют общий интерфейс T.Я хочу написать функции, которые работают как с A, так и с B через интерфейс T.

. В C ++ я хотел бы, чтобы T был абстрактным суперклассом A и * 1011.* и пишите функции, принимающие параметр типа T.

В Rust кажется, что у меня есть два хороших решения.

Перечисления

enum T { 
    A { /* ... */ },
    B { /* ... */ },
}

impl T {
   fn method(&self) {
       match *self {
           // ... 
       }
   } 
}

В методах T я могу сопоставить вариант, чтобы специализировать тип, а затем написать все, что я хочу, при доступе к вариантным членам.Затем я могу написать функции, которые принимают параметры типа T напрямую:

fn f(t: T) {
    // I can use t.method here
}

Черты

trait T {
    // ...
}

struct A { /* ... */ }
struct B { /* ... */ }

impl T for A {
   fn method(&self) {
      // ...  
   } 
}

impl T for B {
   fn method(&self) {
      // ...    
   }
}

С чертами тип уже специализирован в определениях методов.Однако, чтобы использовать T.method, мне нужно написать обобщенную функцию:

fn f<X: T>(t: X) {
    // I can use t.method here
}

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

Принимая во внимание этот факт, какой выбор выбирают авторы библиотек и почему?

Обратите внимание, что меня не волнует, в частности, наследование, я не собираюсь импортировать идиомы C ++ в Rust,Я пытаюсь понять, что является лучшей альтернативой.

1 Ответ

0 голосов
/ 06 июня 2018

Предпочитают ли авторы библиотек использовать перечисления или признаки?

Предпочитают ли строители использовать гвозди или шурупы?

Поддерживают ли врачииспользовать клей, швы или скобки?

Это бессмысленная дихотомия.Обе возможности существуют, и оба используются.Люди используют правильный инструмент для конкретной работы под рукой.

Начните с того, что вернитесь назад и перечитайте Язык программирования Rust глава Is Rust a ObjectОриентированный язык программирования? .

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

реализация раскрыта: подпись f отличается в обоих примерах

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

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

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

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

Если вы измените свой API, ваши пользователи будут затронуты .

Мне нужно написать универсальную функцию

Вам не нужно , нужно , но вам, вероятно, следует использовать ее по умолчанию из соображений производительности.Вы можете использовать объект-черту, например fn f(t: &T) или fn f(t: Box<T>), если <T> вызывает испуг.

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

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

enum Pet {
    Cat,
    Dog,
    Other(Box<Animal>),
}

trait Animal {}
trait TimeSource {
    fn now() -> u64;
}

enum Builtin {
    Ntp,
    Sundial,
}

impl TimeSource for Builtin {
    // ...
}

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

...