Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум на Исходниках.RU > Rust > ООП на Rust |
Автор: JoeUser 10.03.18, 11:26 |
Приветствую! Решил ознакомится с Rust, но не заметил там "нативной" поддержки ООП. Тем не менее, конструкции языка позволяют применять инструментарий ООП. Нашел неплохую статью про это. Но увы, цельного примера я там не нашел, все расписывалось кусками. А хотелось бы в качестве резюме - полноценный пример. Кому не лениво, и кто в теме, прошу составленный мною синтетический пример на C++ перевести на Rust: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> #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 реализовать абстрактный класс, виртуальный метод, и как работать с перекрытием методов? |
Автор: korvin 10.03.18, 13:56 |
Так включи воображение и собери цельный пример. =) Ну как-то так, например: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> 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()); } } |
Автор: JoeUser 10.03.18, 14:04 |
Это после включения обучения обычно делается ![]() |
Автор: korvin 10.03.18, 14:12 |
ХЗ, никакое обучение не проходил, раст видел только мельком, по статье и паре небольших статеек Rust by Example (чтобы синтаксические мелочи подсмотреть), слепил то что слепилось. =) |
Автор: JoeUser 10.03.18, 14:34 |
Ну не спорю - кросава! ![]() |
Автор: OpenGL 10.03.18, 20:38 |
Цитата JoeUser @ Пока не пойму, как в Rust реализовать абстрактный класс, виртуальный метод, и как работать с перекрытием методов? Виртуальные методы делаются trait-ами, как в примере выше. Абстрактный класс сделать нельзя - trait содержит только методы, но не поля, т.е. они ближе к интерфейсам, чем к абстрактому классу. Динамический полиморфизм делается в точности как в плюсах - через указатель/ссылку на базу(trait). Например, если переписать пример korvin-а со ссылок на указатели (класс Box - полный аналог std::unique_ptr из плюсов), то объявление массива v в main будет таким: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> 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)), ]; |
Автор: JoeUser 11.03.18, 07:04 |
korvin, OpenGL, если я не ошибаюсь - в ваших кодах, в конце, заполнение вектора идет путем инициализации при объявлении. А нужно было добавлением. Но это так - мелочи. Просто маленькое несоответствие. Ваш вариант скорее всего бы соответствовал этому куску кода нс C++: <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> std::vector<Figure*> V = { new Rectangle(2,3), new Square(4), new Ellipse(2,3) }; |
Автор: korvin 11.03.18, 10:54 |
Цитата JoeUser @ если я не ошибаюсь - в ваших кодах, в конце, заполнение вектора идет путем инициализации при объявлении. А нужно было добавлением. Это не относилось к вопросу, сделал так как было в примерах в статьях. Ты как-то вяло знакомишься с Rust, мог бы легко сам нагуглить. <{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}> ... 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 |
Автор: JoeUser 11.03.18, 17:10 |
Еще раз - пасип. Да. Есть такое - вяло, мотивации немного недостаточно. |