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