web-dev-qa-db-ja.com

Delphiオブジェクトが特定のクラスのものであり、子孫クラスのものではないかどうかを確認するにはどうすればよいですか?

私はこれらのクラスと手順を持っています:

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

 Procedure DoSomething(obj:TParent);

私がやりたいのは、objTParentであり、子孫ではない場合に例外を発生させることです。

私はこのようなことをすることを考えました:

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

しかし、それは少しハックっぽい(TM)のようです

詳細:私が意図したのは、プロパティ/手順を共有するオブジェクトを渡すことができるようにすることです。さらに考えてみると、TParentオブジェクトは実際にはまったく必要ありません。必要なのは、回答に示されているインターフェイスオブジェクトでした。

20

私は私がやろうとしていたことを解決したと思います、それは昨夜私に頭を打った。

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

Procedure DoSomething(obj:iParentInterface);
0

おそらく、次のTObjectクラスメソッドが役立つでしょう。

  • ClassType -オブジェクトのクラスを返します
  • ClassParent -クラスの親クラスを指定します
  • InheritsFrom -クラスが別のクラスから継承するかどうかを返します(つまり、継承チェーン全体をチェックします)。現在のクラスが含まれます。

したがって、次のコード(テストされていない、現時点ではDelphiがない)のようなものを使用して、必要なもの(TParentから降りるが、TDescendantからは降りない?)を達成できます。

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

または、私が誤解していて、オブジェクトがTParentであり、子孫ではないかどうかを確認したい場合は、次のことを試してください。

if obj.ClassType = TParent then...

Delphiは、 metaclasses を介してクラスへのアクセスを提供することにより、時代をはるかに超えていたため、クラス名を確認するだけでなく、実際のクラスオブジェクトにアクセスできます。

34
David

あなたは正しい方向に進んでいますが、クラス名を比較する代わりに、ClassTypeプロパティをチェックする方が簡単です。

if obj.ClassType = TParent then raise exception.create....
11
Mason Wheeler

オブジェクト指向プログラミングのグッドプラクティスでは、これを行うべきではないと述べています。あなたが説明しているのは、 リスコフの置換原則 の直接の違反であり、次のように述べています。

プログラム内のオブジェクトは、そのプログラムの正確性を変更することなく、サブタイプのインスタンスで置き換えることができる必要があります

解決しようとしている問題を説明しておけば、より良いアプローチが明らかになるかもしれません。

11
David Heffernan

別のアプローチ:TParentに抽象メソッド、たとえばCheckValidChildを導入し、子孫クラスでオーバーライドします。これで、obj.CheckValidChildを呼び出すと、objのインスタンスがTParentクラスの場合、EAbstractErrorが返されます。

3
Uwe Raabe