私はこれらのクラスと手順を持っています:
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オブジェクトは実際にはまったく必要ありません。必要なのは、回答に示されているインターフェイスオブジェクトでした。
私は私がやろうとしていたことを解決したと思います、それは昨夜私に頭を打った。
iParentInterface = interface(IUnknown);
TChild1 = class(TInterfacedObject,iParentInterface);
TChild2 = class(TInterfacedObject,iParentInterface);
Procedure DoSomething(obj:iParentInterface);
おそらく、次のTObject
クラスメソッドが役立つでしょう。
したがって、次のコード(テストされていない、現時点ではDelphiがない)のようなものを使用して、必要なもの(TParentから降りるが、TDescendantからは降りない?)を達成できます。
if obj.ClassType.InheritsFrom(TParent)
and not obj.ClassType.InheritsFrom(TDescendant) then...
または、私が誤解していて、オブジェクトがTParentであり、子孫ではないかどうかを確認したい場合は、次のことを試してください。
if obj.ClassType = TParent then...
Delphiは、 metaclasses を介してクラスへのアクセスを提供することにより、時代をはるかに超えていたため、クラス名を確認するだけでなく、実際のクラスオブジェクトにアクセスできます。
あなたは正しい方向に進んでいますが、クラス名を比較する代わりに、ClassType
プロパティをチェックする方が簡単です。
if obj.ClassType = TParent then raise exception.create....
オブジェクト指向プログラミングのグッドプラクティスでは、これを行うべきではないと述べています。あなたが説明しているのは、 リスコフの置換原則 の直接の違反であり、次のように述べています。
プログラム内のオブジェクトは、そのプログラムの正確性を変更することなく、サブタイプのインスタンスで置き換えることができる必要があります
解決しようとしている問題を説明しておけば、より良いアプローチが明らかになるかもしれません。
別のアプローチ:TParentに抽象メソッド、たとえばCheckValidChildを導入し、子孫クラスでオーバーライドします。これで、obj.CheckValidChildを呼び出すと、objのインスタンスがTParentクラスの場合、EAbstractErrorが返されます。