Ответы пользователя по тегу ООП
  • Какую архитектуру выбрать для программы на Qt?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Я бы посоветовал:
    • Не делать главный класс окна божественным объектом. Его нужно разделить на контролы-модули с их собственной кастомной логикой, валидацией и прочим, а связать между собой - сигналами и слотами.
    • Отделять бизнес-логику от интерфейса. Для чего использовать внедрение зависимостей и абстрактные (чисто виртуальные) классы для декларирования API.


    Допустим, парсером парсится конфиг в объект настроек, эти настройки передаются в фабрику, которая с оглядкой на них будет выдавать правильно сконфигурированные объекты по запросу. Ссылка на фабрику передается в класс окна, откуда добываются зависимости и передаются дальше контролам по ссылке. Контролы, получая зависимость (допустим, через конструктор), привязываются к ней через сигналы/слоты или непосредственно вызывают виртуальные методы.

    Итог: интерфейс декомпозирован, о бизнес-логике он не знает ничего, кроме предоставленного абстрактного API. Контролы знают друг о друге только в рамках сигналов/слотов между собой и списка зависимостей своих детей. Бизнес-логика не знает ничего об интерфейсе.
    Ответ написан
    Комментировать
  • C#: Как правильно прочитать и записать объекты в ArrayList?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Не стоит использовать ArrayListбез весомой на то необходимости. Поэтому компилятор не смог вас предупредить, что ArrayListсостоит из ArrayList'ов, в котором строки (двумерный массив строк), а не просто строк.

    Вместо ArrayListнеобходимо использовать типизированный динамический массивList<string>.

    public void Click_OpenFile()
    {
        string fileName = form1.OpenFie();
    
        IList<string[]> aL = ParseFile(fileName);
    
        foreach (var line in aL)
        {
            // Снова собираем токены в строки
            MessageBox.Show(string.Join(" ", line));
        }
    }
    
    // Читаем файл и построчно парсим его
    private IList<string[]> ParseFile(string fileName)
    {
        if (string.IsNullOrEmpty(fileName))
        {
            throw new ArgumentNullException(nameof(fileName));
        }
        if (!File.Exists(fileName))
        {
            throw new ArgumentException($"There is no file {fileName}!");
        }
    
        string[] fileContent = File.ReadAllLines(result);
        var aL = new List<string[]>(fileContent.Length);
        foreach (var line in fileContent)
        {
            aL.Add(ParseString(line));
        }
        return aL;
    }
    
    // Разбиваем строки на токены
    private string[] ParseString(string s)
    {
        const char delimiter = '|';
        return s.Split(delimiter);
    }
    Ответ написан
    Комментировать
  • Зачем делают так много методов в классе?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Потому что в будущем вы сможете безболезненно добавить логику в метод (получение значения из конфига, из базы, вызов проверки авторизации и т.п., для сеттера - валидация данных). Если же у вас будет голое поле, то придется изменять клиентский код, а это нарушает абстракцию.

    Правило хорошего тона: API класса должен быть доступен только через методы или properties (что, по сути - синтаксический сахар над методами), а поля должны быть только private/protected.
    Ответ написан
    1 комментарий
  • JavaScript; Что не так с моей функцией-модулем (object)?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    var Human = (function (person) {
    
        this.firstName = "John";
        this.lastName = "Doe";
        this.age = person.age || 50;
        this.eyeColor = person.eyeColor || "blue";
    
        this.toString = function() {
            return person.age + ", " + person.eyeColor;
        };
    });
    
    var pers = new Human({ eyeColor: "Yellow" });
    // 
    
    console.log(pers);


    Выглядеть в конечном итоге это может как-то так:
    var SampleClass = (function(localFirstDependencyName, localSecondDependencyName){
        'use strict';
        
        var _defaultSettings = {
            option: 'option'
        }
    
        var constructor = function(settings){
            this._settings = $.extend(this._settings || {}, _defaultSettings, settings);
        
            this.publicField = null;
            this._protectedField = null;    
            this._privateField = null;
        };
            
        $.extend(constructor.prototype, {
            publicConstant: 'Constant',
            protectedConstant: 'Constant',
            _privateConstant: 'Constant',
    
            //#region Public
            publicMethod: function () {      
                this._protectedMethod();    
            },
            //#endregion
            
            //#region Protected
            _protectedMethod: function () {         
            },
            //#endregion
    
            //#region Private
            _privateMethod: function(self, value){
            },  
            //#endregion
        });
            
        return constructor;
    }(globalFirstDependencyName, globalSecondDependencyName));
    Ответ написан
    Комментировать
  • Перегрузка операций с++?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Мне кажется, в задании имелось в виду перегрузка равенства ("=="), т.е. мы можем пройтись по коллекции рабочих и сравнить его с неким эталоном

    class Worker {
        std::string _name;
        ...
    public:
        bool operator==(const Worker& other) const {
             return _name == other.name;
        }
    };
    
    //....
    
    std::vector<Worker> workers = {...};
    int count = std::count(begin(workers), end(workers), Worker("Vasili Pupkin"));
    Ответ написан
    Комментировать
  • Почему такой паттерн не корректен?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Потому что объекты (o и o1) разные, внутри каждого свой obj.

    Сама идея синглтона, что это один объект(типа) на всю программу.

    function Singleton () {
        if (Singleton._instance) return Singleton._instance;
        Singleton._instance = this;
    };
    
    var o = new Singleton();
    var o1 = new Singleton();
    console.log(o === o1); // true
    
    o.prop = 's';
    console.log(o1.prop); // s
    Ответ написан
  • Почему в интерфейсе нельзя использовать protected или private?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Интерфейс предназначен для декларирования внешнего API без уточнения реализации. В нем должны быть лишь публичные члены.

    Вообще говоря, это искусственное ограничение, принятое для удобства. В том же C++ в качестве интерфейсов используются чисто виртуальные (абстрактные) классы без состояния. Наличие же специальной синтаксической конструкции (интерфейсов, как в C# или Java) позволяет явно подчеркнуть, что программиста там не ждет никакого сюрприза и этот тип используется как "клей" между другими классами.
    Ответ написан
    Комментировать
  • В каком типе переменной хранить (м\ж) пол?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    ИМХО, расточительно делать отдельную таблицу под пол. Отлично подойдет (если не уходить в дебри человеческих отклонений):
    enum Sex { 
        Male,
        Female,
        Undefined
    }

    bool? - тоже вариант, но читается хуже.
    Ответ написан
    Комментировать