LINUX.ORG.RU

Наследование в Rust

 , ,


1

8

Здравствуйте. Потихоньку изучаю Rust. Насколько я понял, пробежавшись по документации, в Rust ООП реализовано через struct и trait. Это так? Так вот, как реализовать наследование? Например есть следующий код:

struct Shape {
    x: f64,
    y: f64,
}

trait Circle: Shape {
    
}

trait Square: Shape {
    
}

Как мне в Circle после наследования от Shape создать поле radius? То есть что то типа

trait Circle: Shape {
    radius: f64,
}

Вообще было бы здорово, если бы кто-нибудь рассказал про ООП в Rust. Заранее спасибо большое :)

В Rust нет наследования. ООП в нем, в общем-то, тоже нет.

tailgunner ★★★★★
()

Вообще было бы здорово, если бы кто-нибудь рассказал про ООП в Rust.

В Rust нет наследования. ООП в нем, в общем-то, тоже нет.

ну как, здорово?

anonymous
()
Ответ на: комментарий от anonymous

Здорово постоянно узнавать что-то новое и развиваться. Троллинг твой не уместен.

TigranElGrande
() автор топика

Велосипедить только остается. Заменяешь наследование на композицию и иерархию trait'ов. Ж(

anonymous
()
Ответ на: комментарий от TigranElGrande

struct это данные (множество полей). trait это интерфейс (множество сигнатур функций). Ты можешь написать реализацию некоторого trait-а для некоторого типа (в том числе и для struct). Т.е. можешь создать сущность «данные + поведение».

ООП как такового (как в Java) нет. Но в принципе все задачи, которые ставятся перед ООП, в Rust решать можно.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Трейты, в отличие от интерфейсов, могут включать реализацию.

quantum-troll ★★★★★
()
trait Shape {
    fn get_x(&self) -> f64;
    fn get_y(&self) -> f64;
}

struct ShapeData {
    x : f64,
    y : f64
}

impl Shape for ShapeData {
    fn get_x(&self) -> f64 {
        self.x
    }

    fn get_y(&self) -> f64 {
        self.y
    }
}

trait Circle : Shape {
    fn get_radius(&self) -> f64;
}

struct CircleData {
    parent : ShapeData,
    radius : f64
}

impl Shape for CircleData {
    fn get_x(&self) -> f64 {
        self.parent.get_x()
    }

    fn get_y(&self) -> f64 {
        self.parent.get_y()
    }
}
impl Circle for CircleData {
    fn get_radius(&self) -> f64 {
        self.radius
    }
}

fn main() {
    let base_shape: ShapeData = ShapeData{x: 0.0, y: 0.0};
    let circle: CircleData = CircleData{parent:ShapeData{x: 10.0, y: 10.0}, radius: 5.0};
}

Вот такое вот, блин, там «ООП». Ты бы еще про exceptions спросил=)

anonymous
()
Ответ на: комментарий от anonymous

Код оттуда:

trait Animal {
    // Static method signature; `Self` refers to the implementor type
    fn new(name: &'static str) -> Self;

    // Instance methods, only signatures
    fn name(&self) -> &'static str;
    fn noise(&self) -> &'static str;

    // A trait can provide default method definitions
    fn talk(&self) {
        // These definitions can access other methods declared in the same
        // trait
        println!("{} says {}", self.name(), self.noise());
    }
}

struct Dog { name: &'static str }

impl Dog {
    fn wag_tail(&self) {
        println!("{} wags tail", self.name);
    }
}

// Implement the `Animal` trait for `Dog`
impl Animal for Dog {
    // Replace `Self` with the implementor type: `Dog`
    fn new(name: &'static str) -> Dog {
        Dog { name: name }
    }

    fn name(&self) -> &'static str {
        self.name
    }

    fn noise(&self) -> &'static str {
        "woof!"
    }

    // Default trait methods can be overridden
    fn talk(&self) {
        // Traits methods can access the implementor methods
        self.wag_tail();

        println!("{} says {}", self.name, self.noise());
    }
}

struct Sheep { naked: bool, name: &'static str }

impl Sheep {
    fn is_naked(&self) -> bool {
        self.naked
    }

    fn shear(&mut self) {
        if self.is_naked() {
            // Implementor methods can use the implementor's trait methods
            println!("{} is already naked!", self.name());
        } else {
            println!("{} gets a haircut", self.name);

            self.talk();
            self.naked = true;
        }
    }
}

impl Animal for Sheep {
    fn new(name: &'static str) -> Sheep {
        Sheep { name: name, naked: false }
    }

    fn name(&self) -> &'static str {
        self.name
    }

    fn noise(&self) -> &'static str {
        if self.is_naked() {
            "baaah"
        } else {
            "baaaaaaaaaaaah"
        }
    }
}

fn main() {
    // Type annotation is necessary in this case
    let mut dolly: Sheep = Animal::new("Dolly");
    let spike: Dog = Animal::new("Spike");
    // TODO ^ Try removing the type annotations

    dolly.shear();

    spike.talk();
    dolly.talk();
}

anonymous
()
Ответ на: комментарий от anonymous

если разраб плюсов был под героином, то разрабы раста были под говнецом

anonymous
()
Ответ на: комментарий от anonymous

Адовый синтаксис. Аж подсветка слетела. И эти люди ещё ругают C++

anonymous
()
Ответ на: комментарий от quantum-troll

Ну ты же понимаешь, что этот пример демонстрирует сами типажи, а не их грамотное использование на практике?

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

(другой анонимус)

anonymous
()
Ответ на: комментарий от anonymous

Я имею в виду то, что пример с кошечками и собачками это одно, а использование инструментов на реальном коде — совсем другое. Поэтому книги вроде «Programming in ‹langname›» такие толстые.

quantum-troll ★★★★★
()
Ответ на: комментарий от quantum-troll

А мне вот кажется, что rust неюзабелен. Без ООП на определенном уровне тяжеловато большие проекты делать. Да и исключений нет. Синтаксис сопоставим с крестами. ХЗ чего они хотят добиться...

anonymous
()
Ответ на: комментарий от Dark_SavanT

Каким образом ты декомпозируешь систему на высоком уровне? Каким образом модифицируешь реализации, наследуя(в широком смысле слова) уже то, что реализовано(и отлажено) и переопределяя что-то в реализации интерфейсной части? Каким образом расширяешь функциональность? ООП без фанатизма - очень хорошая штука. Конечно, если начинать городить фабрики фабрик, инвертировать зависимости и инъектить зависимости, то да, будет ад. Но ведь это зависит от разработчиков...

anonymous
()
Ответ на: комментарий от anonymous

Синтаксис сопоставим с крестами.

Нет. Тут плохо читаемый ML-й синтаксис, и значит массы его не воспримут, в отличие как раз от С++, Java, C#.

anonymous
()
Ответ на: комментарий от quantum-troll

Согласен с Вами. Не понятно как на практике применять теорию.

TigranElGrande
() автор топика

Так вот, как реализовать наследование?

Пока никак, но разные варианты наследования обсуждаются. Язык развивается быстро, думаю скоро будет.

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Без ООП на определенном уровне тяжеловато большие проекты делать.

Какие конкретно проблемы ты ожидаешь с Rust в больших проектах? В Rust что-то мешает применять принципы SOLID?

Да и исключений нет.

Большинство кодеров не может в exception-safe код. В типичном случае кодеры прямолинейно и бездумно используют guard-ы. Так что когда исключение на самом деле вылетает, программа приходит в неконсистентное логическое состояние. Покрытие таких сценариев юнит-тестами обычно околонулевое. В общем, исключения — это крайне неоднозначная штука; а если ты хочешь писать программы с упором на надежность, то скорее вредная, чем полезная.

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 1)
Ответ на: комментарий от DarkEld3r

Язык развивается быстро, думаю скоро будет.

Даешь rust++ с ООП!

anonymous
()
Ответ на: комментарий от anonymous

Без ООП на определенном уровне тяжеловато большие проекты делать.

В чем именно трудности?

anonymous
()
Ответ на: комментарий от anonymous

Лол, сходи в википедию, посмотри, как на самом деле выглядят «нечитаемые» ML-и, и сравни с {}-нойзом из топика.

anonymous
()
Ответ на: комментарий от anonymous

Лол, сходи в википедию, посмотри, как на самом деле выглядят «нечитаемые» ML-и, и сравни с {}-нойзом из топика.

Это тебе надо сходить и ознакомиться с OCaml, например. Точно такие же {}.

anonymous
()
Ответ на: комментарий от anonymous

Анон, не тупи. Раст не ML ни разу. Раст - это си-подобная перловка в стиле «кот по клавиатуре погулял». Посмотри примеры по своей ссылке - насколько там код чище и проще того говна, что постят в примерах растоманы.

anonymous
()
Ответ на: комментарий от DarkEld3r

Пока никак, но разные варианты наследования обсуждаются.

А какие варианты? Мне понравилось, как в Scala сделано. Наверное, самая любимая реализация ООП. Но там тоже есть свои компромиссы для взаимодействия с Java, тут же можно было продумать все изначально...

anonymous
()
Ответ на: комментарий от Manhunt

В Rust что-то мешает применять принципы SOLID?

Отсутствие поддержки ООП, например=)

Большинство кодеров не может в exception-safe код.

Возможно, стоит подумать над улучшением механизма. В Java почему-то кодеры могут исключения.

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

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

anonymous
()
Ответ на: комментарий от anonymous

Раст не ML ни разу. Раст - это си-подобная перловка

Ну да, ну да. Алгебраически типы, pattern matching, вывод типов - всё это взято из Си.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

В чем именно трудности?

В большом количестве кода. Это большое число подсистем очень хорошо, как правило, ложиться на ОО-модель. Мы легко можем заменять одни компоненты другими, добавлять новую функциональность, без ущерба для старого кода, очень большая часть кода переиспользуется и пр. и пр. Возможно, я просто не умею функциональщину(хотя использую ее на более локальном уровне) или что ты там предлагаешь взамен ООП...

anonymous
()
Ответ на: комментарий от tailgunner

У антоши синтаксис головного мозга. Лечится резекцией лобных долей и приобщением к физическому труду.

Manhunt ★★★★★
()
Ответ на: комментарий от anonymous

Это большое число подсистем очень хорошо, как правило, ложиться на ОО-модель

Большое количество подсистем хорошо ложится на модель «интерфейс-реализация».

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Ты путаешь модульность и ООП.

anonymous
()
Ответ на: комментарий от anonymous

Какие конкретно проблемы ты ожидаешь с Rust в больших проектах? В Rust что-то мешает применять принципы SOLID?

Отсутствие поддержки ООП, например=)

Что конкретно из solid не получается сделать?

Manhunt ★★★★★
()
Ответ на: комментарий от anonymous

Это большое число подсистем очень хорошо, как правило, ложиться на ОО-модель. Мы легко можем заменять одни компоненты другими, добавлять новую функциональность, без ущерба для старого кода, очень большая часть кода переиспользуется и пр. и пр.

Это все спокойно делается с трейтами, не?

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

S

С этим ок

O

Тут проблемы, поскольку без наследования это делается только руками(реализация интерфейса + агрегирование).

L

В rust справедливо лишь в отношении интерфейсной части

I

Вот тут можно сказать даже отлично

D

Тут тоже очень даже неплохо

anonymous
()
Ответ на: комментарий от tailgunner

Большое количество подсистем хорошо ложится на модель «интерфейс-реализация».

Ага, еще, например, неплохо бы иметь модули/классы, открытые для расширения и закрытые для модификации... Этого в Rust нет. Нужно костылить, как в примерах кода выше.

anonymous
()
Ответ на: комментарий от Manhunt

В основном это касается O и частично L.

anonymous
()
Ответ на: комментарий от tailgunner

Алгебраически типы, pattern matching, вывод типов - всё это взято из Си.

Насколько я понимаю, типы выводятся не всегда и не везде, а это несколько противоречит тому, что принято в функциональных языках. Да и императивен Rust насквозь.

anonymous
()
Ответ на: комментарий от tailgunner

Большое количество подсистем хорошо ложится на модель «интерфейс-реализация».

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

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.