![>](style_images/1/nav_m.gif)
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.189.171.134] |
![]() |
|
Сообщ.
#1
,
|
|
|
Приветствую!
Решил ознакомится с Rust, но не заметил там "нативной" поддержки ООП. Тем не менее, конструкции языка позволяют применять инструментарий ООП. Нашел неплохую статью про это. Но увы, цельного примера я там не нашел, все расписывалось кусками. А хотелось бы в качестве резюме - полноценный пример. Кому не лениво, и кто в теме, прошу составленный мною синтетический пример на C++ перевести на Rust: ![]() ![]() #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 реализовать абстрактный класс, виртуальный метод, и как работать с перекрытием методов? |
![]() |
Сообщ.
#2
,
|
|
Цитата JoeUser @ Но увы, цельного примера я там не нашел, все расписывалось кусками. Так включи воображение и собери цельный пример. =) Ну как-то так, например: ![]() ![]() 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()); } } |
Сообщ.
#3
,
|
|
|
Цитата korvin @ Так включи воображение Это после включения обучения обычно делается ![]() |
![]() |
Сообщ.
#4
,
|
|
Цитата JoeUser @ Это после включения обучения обычно делается ХЗ, никакое обучение не проходил, раст видел только мельком, по статье и паре небольших статеек Rust by Example (чтобы синтаксические мелочи подсмотреть), слепил то что слепилось. =) |
Сообщ.
#5
,
|
|
|
Ну не спорю - кросава!
![]() |
![]() |
Сообщ.
#6
,
|
|
Цитата JoeUser @ Пока не пойму, как в Rust реализовать абстрактный класс, виртуальный метод, и как работать с перекрытием методов? Виртуальные методы делаются trait-ами, как в примере выше. Абстрактный класс сделать нельзя - trait содержит только методы, но не поля, т.е. они ближе к интерфейсам, чем к абстрактому классу. Динамический полиморфизм делается в точности как в плюсах - через указатель/ссылку на базу(trait). Например, если переписать пример korvin-а со ссылок на указатели (класс Box - полный аналог std::unique_ptr из плюсов), то объявление массива v в main будет таким: ![]() ![]() 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)), ]; |
Сообщ.
#7
,
|
|
|
korvin, OpenGL, если я не ошибаюсь - в ваших кодах, в конце, заполнение вектора идет путем инициализации при объявлении. А нужно было добавлением. Но это так - мелочи. Просто маленькое несоответствие. Ваш вариант скорее всего бы соответствовал этому куску кода нс C++:
![]() ![]() std::vector<Figure*> V = { new Rectangle(2,3), new Square(4), new Ellipse(2,3) }; |
![]() |
Сообщ.
#8
,
|
|
Цитата JoeUser @ если я не ошибаюсь - в ваших кодах, в конце, заполнение вектора идет путем инициализации при объявлении. А нужно было добавлением. Это не относилось к вопросу, сделал так как было в примерах в статьях. Ты как-то вяло знакомишься с Rust, мог бы легко сам нагуглить. ![]() ![]() ... 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 |
Сообщ.
#9
,
|
|
|
Цитата korvin @ ы как-то вяло знакомишься с Rust Еще раз - пасип. Да. Есть такое - вяло, мотивации немного недостаточно. |