powered by simpleCommunicator - 2.0.48     © 2025 Programmizd 02
Форумы / Публикации участников форума [игнор отключен] [закрыт для гостей] / Как нарушить принцип подстановки Лисков не привлекая внимания санитаров+
1 сообщений из 1, страница 1 из 1
Как нарушить принцип подстановки Лисков не привлекая внимания санитаров+
    #40141012
Фотография tchingiz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
или 'арифметические вычисления и небезопасность универсального полифорфизма'

проект
arithmetic -- классы для для симплекс метода
побочный эффект - разный результат в вычислениях (3 * 5) / 2
из-за разного округления в классе целых.

Очередной пример нарушения принципа, который сводит к нулю
пользу от универсального полиморфизма в обеих формах.
Как от полиморфизма включения, так и от полиморфизма шаблонов.

Есть две версии полиморфной функции:
одна написана в терминах базового класса (каталог v2/PrgFunc.cs)
Код: C#
1.
2.
3.
4.
    static int function ( number one,  number two, number toChangeVal) {
       number out1 = (one * two ) /  toChangeVal;
       return (int) out1;
    }
вторая, как шаблон (каталог v3/PrgFunc.cs):
Код: C#
1.
2.
3.
4.
5.
    static int
    function<T> ( T one,  T two, T toChangeVal) where T : number  {
       number out1 = (one * two ) / toChangeVal;
       return (int) out1;
    }
Округление до целого в них выполняется при помощи обычного отбрасывания дробной части:
(int) out1;

Но в классе целых деление переопределено так, что используется банковское округление
и 15 : 2 дает 8

в результате обе версии полиморфной функции возвращают
разные значения то ли 7, то ли 8 в зависимости от реального класса объектов.

Это результат (надеюсь) всем известных проблем с условиями
контра- и ко- вариантностью
функционального типа метода. Эти условия всем разжевали Б.Мейер и Л.Карделли.
для методов (функций) у которых множество объектов класса появляется
с левой и с правой стороны функциональнй стрелки:

f: domen(class) >< X -> domen(class) >< Y
(для любых множеств X и Y)
/*
Стало понятно после формального анализа примера Мартина
с наследованием квадратов и прямоугольников
в статье Об отличиях между понятиями типа и класса
https://www.researchgate.net/publication/344177979
, что условия в родительском классе можно задавать таким образом, что область определения
и множество значений метода не будет меняться. Но к нарушению принципа подстановки будет приводить.
*/

В такую группу методов попадают все алгебраические операции:
domen(class) >< domen(class) -> domen(class)
То есть, функции для вычисления чего либо, скорее всего, нельзя писать
полиморфные.
/*
в Переопределении сложения: небезопасное наследование
в группе целых
(https://www.researchgate.net/publication/366867037)
приводился пример с проблемой на операциях вычитания, переход от полугруппы натуральных к группе целых)

*/

В частности, в этом примере, проблема заключается в операциях деления (переход от кольца целых к полю вещественных)
Код: C#
1.
2.
3.
4.
  // class integer
  public  override  number div( number r){
          return new integer (round( v / round(r.v)));
        }
И
Код: C#
1.
2.
3.
4.
 // class real
    public  override  number div( number r){
          return new integer (v / r.v));
        }
Мейер и Карделли показывали пальцем на эксепшены полиморфной функции.
в текущем примере полиморфные функции (function) не выбрасывает эксепшен,
а тихонько начинает нарушать начальное требования
-- для округления использовать отбрасывание
дробной части. Это еще хуже, чем эксепшн.

Классы integer и real были отлажены, что бы показать как плохо
станет работать полиморфный симплекс метод.
В текущем примере результат сем-восем еще такое дело,
а неправильная оптимизация в симплекс методе явно будет нарушать
начальную спецификацию при попытке использовать универсальный полиморфизм.

Виды округления в Си Шапре согласно IEEE 754 -2019
Округление к ближайшему или четному (Банковское округление)
Math.Round(v, MidpointRounding.ToEven)
Округление к ближайшему или большему по модулю
Math.Round(v, MidpointRounding.AwayFromZero)

выбирается ближайшее целое число, а если их два - то,
в первом случае -- четное, во втором -- большее по модулю.

Округление отбрасыванием дробной части
(int) v или Math.Truncate(v)

Округление к положительной бесконечности
из двух целых чисел выбирается большее:
Math.Ceiling(v) или
Math.Round(value, MidpointRounding.ToPositivetiveInfinity)
Округление к отрицательной бесконечности
из двух целых чисел выбирается меньшее:
Math.Floor(v ) или Math.Round(value, MidpointRounding.ToNegativetiveInfinity)
arithmetic_02.00.01.zip
...
Изменено: 26.06.2025, 19:24 - tchingiz
Рейтинг: 0 / 0
1 сообщений из 1, страница 1 из 1
Форумы / Публикации участников форума [игнор отключен] [закрыт для гостей] / Как нарушить принцип подстановки Лисков не привлекая внимания санитаров+
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]