4

私はNhibernate3.0を学んでいます。サンプルコード例の1つでは、抽象基本エンティティクラスを作成します。

public abstract class Entity<T> where T : Entity<T>

次に、CustomerエンティティをEntity基本クラスから継承させます。

public class Customer : Entity<Customer>

私はそれが抽象ジェネリッククラスであることを理解しています、そしてそれはタイプが でwhereあることを確認するためにキーワードを使用しています、これは私が混乱するところです。TEntity<T>

Customer「」から継承しますがEntity<Customer>、この「Entity<Customer>」は「Customer」をとして取りますTが、これCustomerは「」ではありませんEntity<T>

これを理解するのを手伝ってください、私はこのジェネリッククラスに本当に混乱しています。

4

4 に答える 4

8

あなたが言った

顧客は「エンティティ」から継承し、この「エンティティ」は「顧客」をTとしますが、この顧客は「エンティティ」ではありません

それが継承の意味であるため、それは意味がありません。それは「isa」関係を確立します。したがって、実際にはaCustomerEntity

申し訳ありませんが、コードブロックに含まれていなかったため、ジェネリックが削除されたコードに基づいていました。

ただし、同じ原則が引き続き有効です。再帰的定義のように見えるので少し混乱しますが、そうではありません。

Customer継承元と考えてください。Entity ジェネリックパラメータ自体に依存するメソッドまたはフィールドがたまたまありますCustomer。私はNHibernateに精通していないので、残りの部分がどのEntity<T>ように見えるかはわかりませんが、それ自体の型を汎用パラメーターとして使用するメソッドがいくつかあると思います。

たとえば、次のようなメソッドがあるとします。

public IEnumerable<T> GetEntities() 

それはそれ自身のインスタンスのリストを返しました。基本型ではなく具象型を返すには、そのメソッドが必要です。したがって、Customerクラスでは、そのメソッドは次のようになります。

public IEnumerable<Customer> GetEntities<Customer>() 

ジェネリックパラメータがない場合は、IEnumerable<Entity>

それはそれがどのように使われることができるかの一例に過ぎません、私はそれが実際にどのように使われるかわかりません。

于 2011-12-06T02:34:00.683 に答える
1

基本の「エンティティ」クラスが実行しようとする操作を検討すると、より意味があります。私もnhibernateに精通していませんが、メソッドの1つがSave()メソッドに似ているかもしれないと想像します。したがって、Entityクラスから継承するクラスを作成すると、Save()メソッドが継承されるため、作成するビジネスオブジェクトごとにクラスを書き直す必要がなくなります。ただし、Baseエンティティクラスは、保存しようとしているオブジェクトのタイプを認識している必要があります。リフレクションを使用することもできますが、ここではジェネリックスを使用して、エンティティを継承しているクラスの種類を指定できるようにしています。

問題は、20の異なるクラスが基本クラスから継承する場合、その基本クラスは、誰がその機能を使用しているかについての知識を実際には持っていないということです。これは、「顧客」がそのメソッドを使用していることを基本クラスに通知して、「顧客」のニーズに特に対応できるようにする方法です。

于 2011-12-06T02:58:05.397 に答える
0

このwhere句は、置換されるタイプがT従わなければならない条件を指定します。したがって、コードの2行目のCustomerように、型がである場合、条件は...です。つまり、のサブクラスである必要があります。そうでない場合は、コンパイルエラーが発生します。そして実際、それはそのように宣言されています。これもコードの2行目です。Entity<Customer>Customer : Entity<Customer>CustomerEntity<Customer>

あなたが書いたものにこれを適用する:

この「Entity<Customer>」は「顧客」をTとして取ります

これが私がそれをどのように置くかです:は、の代わりにとEntity<Customer>のインスタンス化です。あるタイプの単なるプレースホルダーです。型パラメータです。Entity<T>CustomerTT

しかし、この顧客は「Entity<T>」ではありません

の代わりにSomeTypeを使用して抽象メソッド宣言を作成することもできTます。条件は、SomeTypeをインスタンス化するためにEntity<> SomeTypeEntity<SomeTypeのサブクラスである必要があるということです>。SomeTypeCustomer代わりに、それはCustomerのサブクラスでなければならないということですEntity<Customer>、そしてそれはそうです。

それが単なるパラメータであり、の場合はそれが代用されることを理解しているT場合Customerこの顧客は「 」Entity<Customer>ではない」と言う理由がわかりません。 )の定義のすべての出現で。Entity<T>Customer : Entity<Customer>CustomerTEntity<T>

于 2011-12-06T02:56:28.247 に答える
0

このような継承をどのように使用できるかを示すサンプル:

class Creatable<T> where T:Creatable<T>, new()
{
 pulibc static T Create()
 {
   T t = new T(); // we know to call new due new() constraint
   t.FinishCreation(); // we know that T implements this method due Creatable<T> constraint
   return t;
 }
 public void SomeOtherUsefulsOperation(){};
 protected virtual void FinishCreation(){};
}

class Child:Creatable<Child>
{
 public Child(){};
 protected override void FinishCreation(){/*do something special for this type */};}
}

// somewhere else
void DoSomething<T>() where T:Creatable<T>
{ 
 T item = Creatable<T>.Create();
 item.SomeOtherUsefulOperation();
}
于 2011-12-06T03:30:44.513 に答える