Инкапсуляция и исключения - PullRequest
3 голосов
/ 14 марта 2012

Я проектирую свой собственный ОО-язык и радостно шел вперед, пока не наткнулся на исключения.Мне кажется, что исключения нарушают инкапсуляцию.

Например, если класс A имеет объект класса B, B имеет C, а C имеет X, что вызывает исключение для A, код в A не должентолько знать о X, но также B и C, чтобы справиться с этим правильно.Вы можете сказать это, потому что если вы замените C на D, обработчик исключения должен будет измениться, чтобы извлечь соответствующую информацию из стека вызовов.часть API класса, чтобы они передавали обратно в стек вызовов по одному вызывающему.И они должны повторно прервать исключение в своих собственных терминах.

Вот пример.Тренд - это класс для анализа статистических трендов, в котором есть метод наклона для расчета наклона линии из двух точек.

method slope
    given
        Point 1st
        Point 2nd
    returns
        Number m
    except
        when infinite slope

    m gets
        ( 2nd's y - 1st's y ) / ( 2nd's x - 1st's x )
    except
        when any divide by zero
            declare infinite slope
        when overflow of ( 2nd's y - 1st's y )
            declare infinite slope
        when overflow of ( 2nd's x - 1st's x )
            instead do m gets 0
        when overflow of ( 2nd's y - 1st's y ) / ( 2nd's x - 1st's x )
            declare infinite slope
        when any underflow
            instead use 0

end of method slope

Есть ли лучший способ сделать это?

Ответы [ 3 ]

2 голосов
/ 16 марта 2012

Реальные исключения попадают в одну из трех грубых категорий:

  • Системные исключения генерируются при возникновении фатальных ошибок в базовой среде выполнения, таких как нехватка памяти, переполнение стека иливозможно нарушения безопасности.Они обычно не должны быть пойманы, и во многих случаях не может быть пойман .Они в основном используют систему исключений для того, чтобы корректно завершить работу системы (и сравнительно) и сообщить разработчику окончательную трассировку стека.

  • Программные исключения генерируются, когда код делает что-то неправильное,Такие вещи, как недопустимые аргументы, вызов методов на нулевых указателях, ошибки за пределами допустимых границ.Они не должны быть пойманы: вместо этого должен быть исправлен код, который вызывает их выброс.Они используют систему исключений, чтобы избежать более или менее избыточной системы assert, которая выполняет большинство одинаковых действий.

  • Исключения во время выполнения генерируются, когда происходит что-то плохое, что не может быть программно предотвращено,Они выбрасываются при возникновении непредвиденных обстоятельств, но достаточно редко, чтобы не загромождать основной API кодами ошибок и т. Д. Это такие вещи, как ошибки ввода-вывода файла, проблемы с сетью, ошибки синтаксического анализа и т. Д. Эти исключенияобычно будет специфичным для API, который их выбрасывает.Это исключения типа only , которые обычно следует отлавливать.

Если вы согласны с приведенной выше разбивкой, инкапсуляция влияет только на третью категорию.Для двух других исключение не фиксируется в коде, поэтому это не имеет значения.Что касается третьего типа исключения, да, я думаю, что вы, как правило, должны перехватить исключение и перевести его в другое исключение, соответствующее слою, который его выбрасывает.Вот почему большинство систем исключений в других языках поддерживают что-то вроде «InnerException», где вы можете прикрепить предыдущее исключение нижнего уровня, которое привело к текущему.

0 голосов
/ 01 мая 2012

Я согласен, что исключения кажутся более структурированными, чем объектно-ориентированные.

Тем не менее, разрешите решить проблему с ошибками.

Например, ... ... для извлечения соответствующей информации из стека вызовов.

Ваш пример в C ++ -подобном псевдокоде :

class XClass {
  public: 
    void doSomething() { throw new MyException(); }
}

class CClass {
  public: 
    XClass X;
}

class BClass {
  public: 
    CClass C;
}

class AClass {
  public: 
    BClass B;
}

void main()
{
  AClass A = new AClass ();

  // exception here:
  A.B.C.X.doSomething();
}

Объект "A" не должен знать о "X" или наоборот, относительно исключений. Должен быть стек исключений, в который все объекты добавляют или удаляют данные выполнения.

«чистый С» не имеет исключений, но их можно эмулировать. Возможно, вы захотите найти библиотеку setjmp и посмотреть, могут ли эти функции взаимодействовать со стеком. Эти знания могут помочь вам реализовать исключения:

http://www.cplusplus.com/reference/clibrary/csetjmp/

P.D. Предложение оффтопа: добавьте пространства имен c ++ или паскаль-модули в вашу прогру. я не пожалею об этом.

0 голосов
/ 16 марта 2012

если вы замените C на D, обработчик исключения должен будет измениться, чтобы извлечь соответствующую информацию из стека вызовов.

Не так, как обычно реализуются обработчики исключений.Промежуточные названные классы могут даже не существовать, когда A компилируется, поэтому построение этой зависимости в A не только сложно, но в принципе невозможно.

...