Показать сообщение отдельно
Старый 08.06.2011, 15:45   #1  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,448 / 1792 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Интересный способ подавить вывод сообщения checkFailed
В общем, делюсь найденной мною фичей.
Известно, что x++ поддерживает написание локальных функции в области описания переменных.
Так же известно, что к методам описанным в классе Global можно обращаться без префикса в виде имени класса (в этом случае работа с ними выглядят так же как со встроенными функциями).
Так вот, оказывается имя локальной функции вполне может совпадать с именем метода класса Global. И тогда она его перекрывает своей областью видимости!
Данное поведение не распространяется на встроенные функции. Если имя такой локальной функции совпадёт с именем встроенной функции (например abs), то компилятор будет ругаться, не позволяя переопределить стандартную функцию.

Где это можно использовать? Я хочу продемонстрировать следующий приём.
Допустим у нас есть некий метод validate, который не просто делает некоторые проверки но и выводит в случае неудачи текст ошибки в инфолог. Скорее всего делает это он при помощи довольно популярного метода checkFailed класса Global.
Предположим, что нам понадобилось воспользоваться этим методом в тихом режиме. Т.е. мы хотим узнать выполнились ли проверки, но не хотим что бы при этом в случае ошибки сообщения выводились в инфолог. Простейшее решение - это добавить входной параметр со значением по умолчанию для совместимости с существующим кодом boolean _showError = true и использовать его для выбора варианта действия.
В случае если наш метод validate содержит несколько проверок, то модификации могут оказаться объёмными. Для того чтобы минимизировать количество правок кода я предлагаю перекрыть в рамках этого кода сам метод checkFailed.
Выглядит это так:
X++:
protected boolean validate(boolean _showError = true)
{
    boolean ret = true;
    // вместо модификации всего кода переопределяем в одном месте checkFailed
    // -->>
    boolean checkFailed(SysInfoLogStr txt)
    {
        return
            _showError
                ? Global::checkFailed(txt)
                : false;
    }
    // <<--
    // остальной код оставляем без изменений
    ;

    if (Fail1)
        ret = checkFailed("Error 1");
    if (Fail2)
        ret = checkFailed("Error 2");
    ...
    if (FailN)
        ret = checkFailed("Error N");

    return ret;
}
С одной стороны всё довольно-таки красиво получилось, а с другой стороны я раньше нигде не встречал подобного приёма. Как думаете?

Последний раз редактировалось S.Kuskov; 08.06.2011 в 15:55.
За это сообщение автора поблагодарили: mazzy (2), Pustik (5), lev (2), JeS (1).