Отказ от ООП - пример C# vs С++ vs Rust
От: Shmj Ниоткуда  
Дата: 17.09.23 09:16
Оценка:
Давайте пока с простейшего примера, потом, возможно, добавлю чуть интереснее:

  C#
namespace ConsoleApp4 {
    internal class Program {
        class Widget {
            public string? ControlName { get; set; }
            public string? ControlId { get; set; }

            public virtual void Render() {
                Console.WriteLine(ControlName + "=" + ControlId);
            }
        }

        class TextEditWidget : Widget {
            public string? Text { get; set; }

            public override void Render() {
                base.Render();
                Console.WriteLine("Text=" + Text);
            }
        }

        class CheckWidget : Widget {
            public bool IsChecked { get; set; }

            public override void Render() {
                base.Render();
                Console.WriteLine("IsChecked=" + IsChecked);
            }
        }

        static void Main(string[] args) {
            List<Widget> widgets = new List<Widget>();

            widgets.Add(new TextEditWidget() { ControlId = "1", ControlName="Text1", Text="text"});
            widgets.Add(new CheckWidget { ControlId = "2", ControlName = "Check1", IsChecked = true});
            
            foreach (var widget in widgets)
            {
                widget.Render();
            }
        }
    }
}


42 строки

  C++
#include <iostream>
#include <string>
#include <vector>
#include <memory>

class Widget {
public:
    std::string controlName;
    std::string controlId;

    Widget(const std::string& controlName, const std::string& controlId) noexcept 
        : controlName(controlName), controlId(controlId) { }

    virtual void Render() {
        std::cout << controlName << "=" << controlId << std::endl;
    }
};

class TextEditWidget : public Widget {
public:
    std::string text;

    TextEditWidget(const std::string& controlName, const std::string& controlId, const std::string& text) noexcept
        : Widget(controlName, controlId), text(text) { }

    void Render() override {
        Widget::Render();
        std::cout << "Text=" << text << std::endl;
    }
};

class CheckWidget : public Widget {
public:
    bool isChecked;

    CheckWidget(const std::string& controlName, const std::string& controlId, const bool isChecked) noexcept
        : Widget(controlName, controlId), isChecked(isChecked) { }

    void Render() override {
        Widget::Render();
        std::cout << "IsChecked=" << isChecked << std::endl;
    }
};

int main() {
    std::vector<std::unique_ptr<Widget>> widgets;

    auto textWidget = std::make_unique<TextEditWidget>("1", "Text1", "text");
    widgets.push_back(std::move(textWidget));

    auto checkWidget = std::make_unique<CheckWidget>("2", "Check1", true);
    widgets.push_back(std::move(checkWidget));

    for (const auto& widget : widgets) {
        widget->Render();
    }

    return 0;
}


59 строк

  Rust
trait Widget {
    fn render(&self);
}

struct BaseWidget {
    control_name: Option<String>,
    control_id: Option<String>,
}

impl Widget for BaseWidget {
    fn render(&self) {
        if let Some(ref name) = self.control_name {
            print!("{}", name);
        }

        print!("=");

        if let Some(ref id) = self.control_id {
            print!("{}", id);
        }

        println!();
    }
}

struct TextEditWidget {
    base: BaseWidget,
    text: Option<String>,
}

impl Widget for TextEditWidget {
    fn render(&self) {
        self.base.render();
        if let Some(ref text) = self.text {
            println!("Text={}", text);
        }
    }
}

struct CheckWidget {
    base: BaseWidget,
    is_checked: bool,
}

impl Widget for CheckWidget {
    fn render(&self) {
        self.base.render();
        println!("IsChecked={}", self.is_checked);
    }
}

fn main() {
    let widgets: Vec<Box<dyn Widget>> = vec![
        Box::new(TextEditWidget {
            base: BaseWidget {
                control_id: Some("1".to_string()),
                control_name: Some("Text1".to_string()),
            },
            text: Some("text".to_string()),
        }),
        Box::new(CheckWidget {
            base: BaseWidget {
                control_id: Some("2".to_string()),
                control_name: Some("Check1".to_string()),
            },
            is_checked: true,
        }),
    ];

    for widget in widgets {
        widget.render();
    }
}


73 строки

Видно что ООП языки — примерно одинаковой компактности, в то время как язык без ООП даже на простейшем примере потребовал писать почти в 2 раза больше строк кода. Хотя там еще добавляется многословность в связи с Option — но кто им виноват, что не использовали ? как в C# на уровне языка, а то постоянно лепят свой Option.

Выводы какие? Даже на простейшем примере видно удобство ООП. А теперь представьте что пример будет реальным — сразу 50 тыс. строк превращаются в 100 тыс.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.