4

我正在学习 Nhibernate 3.0。在其中一个示例代码示例中,它创建了一个抽象基实体类:

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

然后,使Customer实体从Entity基类继承:

public class Customer : Entity<Customer>

我知道它是一个抽象的泛型类,它使用where关键字来确保类型TEntity<T>,这就是我感到困惑的地方。

Customer继承自 " Entity<Customer>",this " Entity<Customer>" 采用 " Customer" as T,但 thisCustomer不是 " Entity<T>"。

请帮助我理解这一点,我真的对这个通用类感到困惑。

4

4 回答 4

8

你说

customer继承自“Entity”,这个“Entity”把“Customer”当作T,但是这个customer不是“Entity”

这没有任何意义,因为这就是继承的意思。它建立了一个“是”的关系。所以实际上 aCustomer是一个Entity

抱歉,这是基于去掉了泛型的代码,因为它不在代码块中。

但同样的原则仍然有效。这有点令人困惑,因为它看起来像是一个递归定义,但事实并非如此。

将其视为Customer继承自Entity There 恰好是依赖于泛型参数本身的方法或字段,例如Customer。我对 NHibernate 不熟悉,所以我不知道其余部分是什么Entity<T>样的,但我想它有一些方法使用它自己的类型作为泛型参数。

比如说它有一个名为的方法

public IEnumerable<T> GetEntities() 

它返回了它自己的实例列表。它需要该方法返回具体类型而不是基本类型。所以在Customer课堂上,该方法将是

public IEnumerable<Customer> GetEntities<Customer>() 

如果它没有泛型参数,它只能返回IEnumerable<Entity>

这只是一个如何使用它的示例,我不知道它实际上是如何使用的。

于 2011-12-06T02:34:00.683 回答
1

当您考虑基本“实体”类尝试执行的操作时,它会更有意义。我也不熟悉 nhibernate,但我想其中一种方法可能类似于 Save() 方法。因此,您创建的任何从 Entity 类继承的类都将继承 Save() 方法,从而使您不必为创建的每个业务对象重写它。但是,Base 实体类必须知道您要保存的对象类型。它可以使用反射,但在这里它使用泛型来让您告诉它继承实体的类是什么。

问题是,当 20 个不同的类从一个基类继承时,该基类实际上并不知道谁在使用它的功能。这是一种让基类知道“客户”正在使用其方法的方法,以便它可以专门满足“客户”的需求。

于 2011-12-06T02:58:05.397 回答
0

where子句指定要替换的类型T必须遵守的条件。所以,如果类型是Customer,就像在Entity<Customer>第二行代码中一样,那么条件是Customer : Entity<Customer>......即,Customer必须是 的子类Entity<Customer>,否则会出现编译错误。确实如此声明,再次在第二行代码中。

将此应用于您所写的内容:

此“ Entity<Customer>”将“客户”作为 T

我是这样说的:Entity<Customer>是 with 的一个实例,Entity<T>Customer替换为T. T只是某种类型的占位符;这是一个类型参数

但是这个客户不是“ Entity<T>

我们也可以用SomeType而不是T. 条件是,为了实例化Entity<SomeType>SomeType必须是Entity<SomeType>的子类。替换SomeTypeCustomer,表示它必须是 的子类,并且确实如此。CustomerEntity<Customer>

如果您理解这T只是一个参数,并且在 的情况下将其替换CustomerEntity<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 回答