Подтвердить что ты не робот

Как определить, имеет ли объект Delphi определенный класс, а не какой-либо класс потомков?

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

 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 вообще не нужен, мне нужен был объект интерфейса, показанный в моем ответе.

4b9b3361

Ответ 1

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

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

Procedure DoSomething(obj:iParentInterface);

Ответ 2

Вероятно, вы найдете следующие методы класса 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 опередила свое время, предоставив доступ к классам через метаклассы, поэтому вместо того, чтобы просто проверять имя класса, вы можете получить доступ к фактическому объекту класса.

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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