"Включение" vs "Наследование" интерфейсов
От: S.Yu.Gubanov Россия http://sergey-gubanov.livejournal.com/
Дата: 28.09.04 10:59
Оценка: +1 :))
"Включение" vs "Наследование" интерфейсов

Хотелось бы узнать кто что думает по поводу замены механизма наследования интерфейсов на механизм включения. Что такое наследование интерфейсов, думаю, всем понятно. Например, если
IA = INTERFACE
  PROCEDURE f();
  PROCEDURE g();
END;
IB = INTERFACE (IA)
  PROCEDURE h();
  PROCEDURE k();
END;

то, интерфейс IB является потомком от IA и, стало быть, имеет все процедуры объявленные в IA. Переменную типа IB можно использовать вместо переменной типа IA. Другими словами, переменная типа IA совместима по присваиванию с переменной типа IB (обратное не верно). Теперь рассмотрим случай когда IA и IB не связаны друг с другом наследованием:
IA = INTERFACE
  PROCEDURE f();
  PROCEDURE g();
END;
IB = INTERFACE
  PROCEDURE f();
  PROCEDURE g();
  PROCEDURE h();
  PROCEDURE k();
END;

Хотя IA и IB не связаны друг с другом наследованием, но интерфейс IB включает в себя все процедуры объявленные в интерфейсе IA. Теоретически, любая переменная типа IB потенциально может быть использована вместо переменной типа IA (компилятор, правда, с этим будет не согласен, но это его проблемы). Будем говорить, что один (включающий) интерфейс включает в себя другой (включаемый) интерфейс, если он включает в себя все процедуры объявленные во включаемом интерфейсе. Сразу же ответим на вопрос сколько более мелких интерфейсов включает в себя один большой интерфейс имеющий N-штук процедур. Очевидно, количество включамых интерфейсов равно:

g(N) = N + N*(N-1)/2! + N*(N-1)*(N-2)/3! + ... = 2^N — 2

Например, для N = 3 имеем g(3) = 2^3 — 2 = 6, то есть
Iabc = INTERFACE
   PROCEDURE a();
   PROCEDURE b();
   PROCEDURE c();
  END;

автоматически включает в себя 6 интерфейсов:

Iab = INTERFACE
   PROCEDURE a();
   PROCEDURE b();
  END;
Iac = INTERFACE
   PROCEDURE a();
   PROCEDURE c();
  END;
Ibc = INTERFACE
   PROCEDURE b();
   PROCEDURE c();
  END;
Ia = INTERFACE
   PROCEDURE a();
  END;
Ib = INTERFACE
   PROCEDURE b();
  END;
Ic = INTERFACE
   PROCEDURE c();
  END;

Это, в некотором смысле, аналогично включению типов (type inclusion)

REAL >= SHORTREAL >= LONGINT >= INTEGER >= SHORTINT >= BYTE

Количество включаемых интерфейсов экспоненциально растет (2^N-2) по мере увеличения количества (N) процедур в интерфейсе. Интерфейс состоящий из N=10 процедур, включает в себя 2^10 — 2 = 1022 более мелких интерфейсов. Интерпретация этого явления очень проста. Вот, например, сколькими интерфейсами обладает калькулятор? Ни в жизнь не сосчитаете. Ведь калькулятором можно еще и гвозди забивать! Когда программист проектирует класс объекта, он определяет какие интерфейсы объекты этого класса будут поддерживать
TMyCalculator = CLASS (TInterfacedObject, ICalculate, IStorable, IPaintable, ...)
  //...
END;

Все интерфейсы поддерживаемые объектами этого класса жестко фиксируются в момент написания класса. Но дело в том, что если интерфейс содержит хотябы с десяток процедур, то разработчику будет не под силу указать даже малую часть всех тех 2^10 — 2 = 1022 возможных вариантов использования объектов этого класса. Программист просто утомиться их перечислять, не говоря о том чтобы еще и каждому из этих подинтерфейсов дать свое уникальное имя (и GUID...). Всвязи с этим, возникает вопрос: А не стоит ли для интерфейсов ввести такое понятие как ВКЛЮЧЕНИЕ ИНТЕРФЕЙСОВ и, соответственно, отказаться от наследования интерфейсов, поскольку включение — есть более мощный механизм нежели механизм наследования?

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

С уважением,
Сергей Губанов
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.