На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
> ООП на Rust , на примере
    Приветствую!

    Решил ознакомится с Rust, но не заметил там "нативной" поддержки ООП. Тем не менее, конструкции языка позволяют применять инструментарий ООП. Нашел неплохую статью про это. Но увы, цельного примера я там не нашел, все расписывалось кусками. А хотелось бы в качестве резюме - полноценный пример.

    Кому не лениво, и кто в теме, прошу составленный мною синтетический пример на C++ перевести на Rust:

    ExpandedWrap disabled
      #include <iostream>
      #include <vector>
       
      // *****************************************************************************
       
      class Figure {
        public:
          virtual double Area() = 0;
          void PrintName() {
            std::cout << "Фигура = " << Name() << " ";
          }
        private:
          virtual std::string Name() = 0;
      };
       
      // *****************************************************************************
       
      class Rectangle: public Figure {
        public:
          explicit Rectangle(double h, double w): H(h), W(w) {}
          double Area() override {
            return H*W;      
          }
        private:
          double H,W;
          std::string Name() override {
            return "Прямоугольник";
          }
      };
       
      // *****************************************************************************
       
      class Square: public Rectangle {
        public:
          explicit Square(double l): Rectangle (l,l) {}
        private:
          std::string Name() override {
            return "Квадрат";
          }
      };
       
      // *****************************************************************************
       
      class Ellipse: public Rectangle {
        public:
          explicit Ellipse(double a, double b): Rectangle (a,b) {}
          double Area() override {
            return Rectangle::Area()*3.1415;      
          }
        private:
          std::string Name() override {
            return "Эллипс";
          }
      };
       
      // *****************************************************************************
       
      int main() {
        std::vector<Figure*> V;
        V.push_back(new Rectangle(2,3));
        V.push_back(new Square(4));
        V.push_back(new Ellipse(2,3));
        for(const auto &i:V) {
          i->PrintName();
          std::cout << ", площадь: " << i->Area() << std::endl;
          delete i;
        }
        return 0;
      }


    Пока не пойму, как в Rust реализовать абстрактный класс, виртуальный метод, и как работать с перекрытием методов?
      Цитата JoeUser @
      Но увы, цельного примера я там не нашел, все расписывалось кусками.

      Так включи воображение и собери цельный пример. =) Ну как-то так, например:

      ExpandedWrap disabled
        use std::io::stdin;
        use std::io::BufRead;
        use std::io::BufReader;
         
        mod figures {
         
            pub trait Figure {
                fn area(&self) -> f64;
                fn printName(&self) {
                    print!("Figure = {} ", self.name());
                }
                fn name(&self) -> &'static str;
            }
         
            pub struct Rectangle {
                w: f64,
                h: f64,
            }
         
            impl Rectangle {
                pub fn new(width: f64, height: f64) -> Rectangle {
                    Rectangle { w: width, h: height }
                }
            }
         
            impl Figure for Rectangle {
                fn name(&self) -> &'static str {
                    "Rectangle"
                }
                fn area(&self) -> f64 {
                    self.h * self.w
                }
            }
         
            pub struct Square {
                rectangle: Rectangle,
            }
         
            impl Square {
                pub fn new(size: f64) -> Square {
                    Square { rectangle: Rectangle { w: size, h: size } }
                }
            }
         
            impl Figure for Square {
                fn name(&self) -> &'static str {
                    "Square"
                }
                fn area(&self) -> f64 {
                    self.rectangle.area()
                }
            }
         
            pub struct Ellipse {
                rectangle: Rectangle,
            }
         
            impl Ellipse {
                pub fn new(a: f64, b: f64) -> Ellipse {
                    Ellipse { rectangle: Rectangle { w: a, h: b } }
                }
            }
         
            impl Figure for Ellipse {
                fn name(&self) -> &'static str {
                    "Ellipse"
                }
                fn area(&self) -> f64 {
                    self.rectangle.area() * 3.1415
                }
            }
        }
         
        fn main() {
            use figures::{Figure, Rectangle, Square, Ellipse};
            let v: [&Figure; 3] = [
                &Rectangle::new(2.0, 3.0),
                &Square::new(4.0),
                &Ellipse::new(2.0, 3.0)
                ];
            for i in v.iter() {
                i.printName();
                println!(", area: {}", i.area());
            }
        }
        Цитата korvin @
        Так включи воображение

        Это после включения обучения обычно делается :lol:
          Цитата JoeUser @
          Это после включения обучения обычно делается

          ХЗ, никакое обучение не проходил, раст видел только мельком, по статье и паре небольших статеек Rust by Example (чтобы синтаксические мелочи подсмотреть), слепил то что слепилось. =)
            Ну не спорю - кросава! :lol:
              Цитата JoeUser @
              Пока не пойму, как в Rust реализовать абстрактный класс, виртуальный метод, и как работать с перекрытием методов?

              Виртуальные методы делаются trait-ами, как в примере выше. Абстрактный класс сделать нельзя - trait содержит только методы, но не поля, т.е. они ближе к интерфейсам, чем к абстрактому классу. Динамический полиморфизм делается в точности как в плюсах - через указатель/ссылку на базу(trait). Например, если переписать пример korvin-а со ссылок на указатели (класс Box - полный аналог std::unique_ptr из плюсов), то объявление массива v в main будет таким:
              ExpandedWrap disabled
                    let v: Vec<Box<Figure>> = vec![
                        Box::new(Rectangle::new(2.0, 3.0)),
                        Box::new(Square::new(4.0)),
                        Box::new(Ellipse::new(2.0, 3.0)),
                    ];
                korvin, OpenGL, если я не ошибаюсь - в ваших кодах, в конце, заполнение вектора идет путем инициализации при объявлении. А нужно было добавлением. Но это так - мелочи. Просто маленькое несоответствие. Ваш вариант скорее всего бы соответствовал этому куску кода нс C++:
                ExpandedWrap disabled
                        std::vector<Figure*> V = {
                          new Rectangle(2,3),
                          new Square(4),
                          new Ellipse(2,3)
                        };
                  Цитата JoeUser @
                  если я не ошибаюсь - в ваших кодах, в конце, заполнение вектора идет путем инициализации при объявлении. А нужно было добавлением.

                  Это не относилось к вопросу, сделал так как было в примерах в статьях. Ты как-то вяло знакомишься с Rust, мог бы легко сам нагуглить.

                  ExpandedWrap disabled
                    ...
                    use std::boxed::Box;
                    use std::vec::Vec;
                     
                    ...
                     
                    fn main() {
                        use figures::{Figure, Rectangle, Square, Ellipse};
                        let mut v: Vec<Box<Figure>> = Vec::with_capacity(4);
                        v.push(Box::new(Rectangle::new(2.0, 3.0)));
                        v.push(Box::new(Square::new(4.0)));
                        v.push(Box::new(Ellipse::new(2.0, 3.0)));
                        for i in &v {
                            i.printName();
                            println!(", area: {}", i.area());
                        }
                    }

                  https://ideone.com/BGynKV
                    Цитата korvin @
                    ы как-то вяло знакомишься с Rust

                    Еще раз - пасип. Да. Есть такое - вяло, мотивации немного недостаточно.
                    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                    0 пользователей:


                    Рейтинг@Mail.ru
                    [ Script execution time: 0,0314 ]   [ 15 queries used ]   [ Generated: 28.03.24, 12:03 GMT ]