Как я могу определить, принадлежит ли объект Delphi к определенному классу, а не к какому-либо классу-потомку? - PullRequest
18 голосов
/ 10 марта 2011

У меня есть эти классы и процедура:

 TParent = class(TObject);
 TChild1 = class(TParent);     
 TChild2 = class(TParent);

 Procedure DoSomething(obj:TParent);

То, что я хотел бы сделать, это когда obj является TParent и не является потомком для исключения.

Я думал о том, чтобы сделать что-то вроде этого:

if obj.classname = TParent.classname then raise exception.create....

но это кажется немного хакерским (TM)

Еще: То, что я намеревалсявозможность передавать объекты с общими свойствами / процедурами.После долгих раздумий объект TParent на самом деле вообще не нужен, мне нужен интерфейсный объект, показанный в моем ответе.

Ответы [ 5 ]

34 голосов
/ 10 марта 2011

Вы, вероятно, найдете следующие TObject методы класса полезными:

  • ClassType - возвращает класс объекта
  • ClassParent - дает родительский класс класса
  • InheritsFrom - возвращает, если класс наследует от другого класса (т. Е. Проверяет всю цепочку наследования). Включает текущий класс.

Итак, вы могли бы достичь того, что вы хотите (происходит от TParent, но не от TDescendant?) С помощью чего-то вроде следующего кода (непроверенный, на данный момент Delphi не имеет):

if obj.ClassType.InheritsFrom(TParent)
  and not obj.ClassType.InheritsFrom(TDescendant) then...

Или, если я неправильно понял, и вы просто хотите посмотреть, является ли объект TParent, а не каким-либо потомком, попробуйте:

if obj.ClassType = TParent then...

Delphi значительно опередил свое время, предоставив доступ к классам через метаклассы , поэтому вместо простой проверки имени класса вы можете получить доступ к реальному объекту класса.

11 голосов
/ 10 марта 2011

Хорошая практика в объектно-ориентированном программировании гласит, что этого не следует делать. То, что вы описываете, является прямым нарушением принципа замены Лискова , который гласит:

объекты в программе должны быть заменяемые экземплярами их подтипы без изменения правильность этой программы

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

11 голосов
/ 10 марта 2011

Вы на правильном пути, но вместо сравнения имен классов было бы проще проверить свойство ClassType.

if obj.ClassType = TParent then raise exception.create....
3 голосов
/ 10 марта 2011

Другой подход: ввести абстрактный метод в TParent, скажем CheckValidChild , и переопределить его в классах-потомках.Теперь, когда вы вызываете obj.CheckValidChild , вы получаете EAbstractError , если экземпляр obj имеет класс TParent.

0 голосов
/ 11 марта 2011

Я думаю, что я решил, что я пытался сделать, Это ударило меня по голове прошлой ночью.

iParentInterface = interface(IUnknown);
TChild1 = class(TInterfacedObject,iParentInterface);     
TChild2 = class(TInterfacedObject,iParentInterface);   

Procedure DoSomething(obj:iParentInterface);
...