• Создание C++-like интерфейса в Python3?

    KirillHelm
    @KirillHelm Автор вопроса
    Нашел следующее решение.
    Интерфейс
    Я создал базовый класс интерфейса InterfaceBase который наследует ABC, для реализации абстрактного класса интерфейса. Так же создал декоратор для класса, который решает следующие задачи:
    1. Наследует базовый класс интерфейса InterfaceBase
    2. Добавляет статический метод create(*args, **kwargs) этому классу именно с помощью этого можно будет создавать имплементацию напрямую из интерфейса (параметры переданные в функцию будут переданы в конструктор класса имплементации при его создании).

    Так что теперь декларация интерфейса выглядит следующим образом:
    @myinterfacedecorator
    class IMyInterface():
       @abstractmethod
       def methodname(self, parameter1, paramer2): pass


    Имплементация
    Теперь перейдем к вкуснятинке - имплементации. Дело в том, что меня интересует два фактора:
    • Оторвать имплементацию полностью от интерфейса, что бы не аффектить ABC классом и его мета-классом на неё
    • Дать возможность подключения разных интерфейсов к одной и той же имплементации

    Для этих целей я для начала сделал следующую цепочку:
    1. class InterfaceImplementationWrapper(object): pass - этот класс является базовым для класса имплементации, в нем я создаю дубликаты абстрактных методов с базовой имплементацией по типу:
      raise NotImplementedError("Method <name> is not implemented!")

    2. А так же класс, что наследует интерфейс и имеет аттрибут с имплементацией абстрактных методов интерфейса внутри себя. Имплементация же абстрактных методов есть суть wrapper-функций, что редеректят все вызовы в инстанс класса имплементации, что является полем в proxy (см. выше).
      class InterfaceImplementationProxy(IMyInterface): pass


    Стоит заметить, что это все я генерирую динамически и оборачиваю в функцию implementInterface.
    Таким образом мы получаем следующий код для декларации класса-имплементации:
    class CMyInterfaceImplementation(implementInterface(IMyInterface)): pass

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

    Подитожим:
    Мы имеем интерфейс отнаследованный от базового класса интерфейсов (объявленный через декоратор @myinterfacedecorator), что в свою очередь является наследником ABC, каждый метод интерфейса объявлен через декоратор @abstractmethod.
    Так же у нас есть имплементация, что отнаследована от wrapper-класса, который имеет методы такие же как в классе интерфейсе (но уже не абстрактные), с базовой имплементацией, которая вызывает exception.

    Фабрика
    Теперь перейдем к механизму, что создает имплементацию - фабрике. Мне показалось удобным создавать методы через статический метод интерфейса create, как упомянул выше. Именно он обращается к фабрике и запрашивает создание нового инстанса имплементации. Вопрос в том, как запросить класс имплементации у фабрики и как класс имплементации попадет в фабрику.
    Фабрика представляет из себя singleton что хранит словарь, где каждому интерфейсу соответствует тип имплементации. Что бы зарегестрировать там новый интерфейс, следует просто вызвать необходимый метод, куда передается полный пусть в проекте к фуйлу интерфейса, имплементации, а так же имена соответствующих классов. Эта функция реализована на функционале библеотеки импортов. Эту функцию проще всего разместить в файле декларации интерфейса, так что она теперь выглядит так:
    @myinterfacedecorator
    class IMyInterface():
       @abstractmethod
       def methodname(self, parameter1, paramer2): pass
    registerInterfaceAndImplementation("project.component.api.interface", "IMyInterface", "project.component.src.implementation", "CMyInterfaceImplementation")


    Каждый раз когда пользователь хочет создать интерфейс, ему нужно только заимпортить api-класс (класс интерфейс) и вызвать его статический метод для создания:
    from project.component.api.interface import IMyInterface
    component = IMyInterface.create(constructorParameter1, constructorParameter2)
    component.method()

    Функция create (она сгенерирована через декоратор myinterfacedecorator) обратиться к фабрике и передаст свой тип (интерфейса) в неё с запросом на создание имплементации. Фабрика проверит наличие соответствия этому интерфейсу класса имплементации, после чего создаст прокси с имплементацией внутри (если такового нет то выкенет exception)

    P.s.
    Знаю что уже существуют либы реализующие подобный функционал. Но есть рестрикшены, что не позволяют их использовать.
    Ответ написан
  • Какая IDE бесплатна под разработку коммерческого приложения под Windows?

    KirillHelm
    @KirillHelm
    Пишите в чем, хотите, вопрос чем вы будете компилировать.

    Конкретизируйте вопрос, если вам нужна библиотека для рисования UI, то это другой вопрос.
    По факту вы можете использовать абсолютно любое IDE бесплатное для редактирования вашего кода.
    Лично я пользуюсь Eclipse для этого по большей части.
    Ответ написан
  • Как достать значение из строки по REGEX в C++0x?

    KirillHelm
    @KirillHelm Автор вопроса
    Нашел решение для C++. Это итератор, ему передается регулярное выражение и при operator++, он будет перескакивать на следующее подходящее по регулярке выражение в строке.
    Ответ написан
  • Вычислить попадет ли точка в заштрихованную область?

    KirillHelm
    @KirillHelm
    Выделяйте явно фигурными скобками область видимости логического блока if.
    Разделите условия на составные части, но сделайте это лучше отдельными переменными, т.е.
    bool isXPosRightThanLine1 = (x >= -K);
    bool isYPosUpperThanLine1 = (y >= -K);
    ...

    Кроме того, вынесети их в отдельную функцию типа:
    bool isPointInArea(const int& xPos, const int& yPos);

    А уже в блоке if у вас получится:
    if (isPointInArea(x,y))
    {
       //do something
    }
    else
    {
       //do something else
    }

    Тем самым вы добьетесь большей читаемости кода и более простой его поддерживаемости.

    Так же как уже говорили в коментах используйте лучше math.h библиотеку для математических вычеслений,
    Ответ написан
  • Как в Qt узнать адрес bluetooth устройства, зная его имя?

    KirillHelm
    @KirillHelm
    Как вариант создать класс CBluetothKeeper, в котором хранить таблицу адресов и названий устройств. Определяем интерфейсы для комбобокса и уже кода, что будет пользовать ваш CBluetothKeeper. На комбобокс выводим соответственно имена, и генерируем событие которое будет отправлять уже адрес, а не имя.
    Ответ написан
  • С++ Как забрать переменную из файла a.ini?

    KirillHelm
    @KirillHelm
    Ну ничего сложного, давайте пойдем самым простым путём.
    #include <fstream>   //библиотека файловых потоков
    #include <string>
    using namespace std;
    
    int main()
    {
        int value;
        string line;
        fstream* fileStream;
    
        fileStream = new fstream("c:/file.ini");   //инстанциируем поток и передаем в конструктор путь к файлу
        getline(*fileStream, line);   //читаем строку первую из файла в string
        value = stoi(line);   //конвертируем string to int, тут уже на фаш вкус, можно как угодно конвертировать
    
        printf("%d\n", value);
        
        system("pause");
        return 0;
    }


    Постскриптум.
    Это самый простой способ, можно и сложнее, просто читать файл побитово и проинициализировать int таким образом, но начните с этого. Если заинтересует тема побитового чтения/записи в файл, то гуглите про флаги файлового потока.
    Ответ написан
  • Что делать, если глючит датчик движения в телефоне LG?

    KirillHelm
    @KirillHelm Автор вопроса
    Нашёл решение: разобрать телефон, отрезал кусочек прозрачного пластика от упаковки наушников старых и сложил его 2 раза, вышел квадратик 4x4mm и толщиной 1.5mm. После раскрутил корпус под крышкой, положил кусочек полученного пластина на место платы, с другой стороны которой находится датчик приближения и аккуратно закрутил крышку, закручивалось туго.
    Результат: датчик прижимается плотнее и расположен ближе к стеклу, начал работать.
    Ответ написан