【问题标题】:Generics vs inheritance (when no collection classes are involved)泛型与继承(不涉及集合类时)
【发布时间】:2010-04-15 03:47:01
【问题描述】:

这是this question的扩展,甚至可能是其他问题的重复(如果是,请原谅我)。我see from MSDN 泛型通常与集合一起使用

泛型的最常见用途 类与集合如 链表、哈希表、堆栈、 队列,树木等在哪里 添加和删​​除等操作 集合中的项目是 以几乎相同的方式执行 无论数据类型如何 存储。

我看到的例子也验证了上面的说法。

有人可以在不涉及任何集合的真实场景中有效地使用泛型吗?

学究式地,我正在考虑制作一个不涉及集合的示例

public class Animal<T>
{
    public void Speak()
    {
       Console.WriteLine("I am an Animal and my type is " + typeof(T).ToString());
    }

    public void Eat()
    {
        //Eat food
    }
}

public class Dog
{
    public void WhoAmI()
    {
        Console.WriteLine(this.GetType().ToString());

    }
}         

而“An Animal of type Dog”将是

Animal&lt;Dog&gt; magic = new Animal&lt;Dog&gt;();

完全有可能让DogAnimal 继承(假设Animal 的非泛型版本)Dog:Animal 因此Dog 是一个 Animal

我想到的另一个例子是BankAccount。可以是BankAccount&lt;Checking&gt;,BankAccount&lt;Savings&gt;。这很可能是Checking:BankAccountSavings:BankAccount

是否有任何最佳实践来确定我们应该使用泛型还是继承?

【问题讨论】:

  • 在需要扩展类时使用继承。在您的示例中,您将 Animal 作为泛型,也就是说,它可以是您分配给它的任何类型。泛型为您的程序提供了一种使用通用接口执行操作的方法。

标签: c# .net generics inheritance


【解决方案1】:

您可能会得到一些更好的答案,但同时考虑一下: 泛型类意味着泛型类和参数类之间的“of”关系。

所有的狗都是动物,因此它们与所有其他动物都有某些属性/品质。如果你使用继承,那么很容易在 Animal 类中实现那些共同的品质,并在后代类中添加品质。但是如果你使用Animal (Of Dog)来实现它,那么:

  1. 您的 Dog 类本身并不是完全合格的狗/动物,因为它的“动物特性”包含在 Animal (Of T) 类中。狗必须以亲子关系与动物联系在一起。
  2. 您的 Animal 类并不是真正的动物:您不能创建一些接受 Animals 作为参数的方法,因为您不能引用全球化的 Animal (Of T) 类。它实际上是具有共同行为的类家族,而不是超类。您将失去与 Animal (Of T) 类之外的动物打交道的好处。

但是,恕我直言,您应该如何考虑泛型: 想想MedicalDoctor(Of T) 类。 Veterinarian(Of T as Animal) 将继承自 MedicalDoctor(Of Animal)DogVeterinarian 将继承自 Veterinarian(Of Dog)

关键点:泛型类和参数类不是紧密耦合和相互依赖的,它们是共存的。

顺便说一句,如果你想看看泛型的一些好的非集合用法,请注意我们拥有的委托:Action(Of T)、Func(Of TResult)、Comparison(Of T)、EventHandler(Of TEventArgs)、 Converter(Of TSource, TResult)...和接口:IEqualityComparer(Of T), IComparer(Of T)...

【讨论】:

    【解决方案2】:

    WCF Channel Factory 是已知的一个真实世界示例。

    从页面:

    public sealed class Test
    {
        static void Main()
        {
            // Code not shown.
        }
    
        public void Run()
        {
            // This code is written by an application developer.
            // Create a channel factory.
            BasicHttpBinding myBinding = new BasicHttpBinding();
    
            EndpointAddress myEndpoint = new EndpointAddress("http://localhost/MathService/Ep1");
    
            ChannelFactory<IMath> myChannelFactory = new ChannelFactory<IMath>(myBinding, myEndpoint);
    
            // Create a channel.
            IMath wcfClient1 = myChannelFactory.CreateChannel();
            double s = wcfClient1.Add(3, 39);
            Console.WriteLine(s.ToString());
            ((IClientChannel)wcfClient1).Close();
    
            // Create another channel.
            IMath wcfClient2 = myChannelFactory.CreateChannel();
            s = wcfClient2.Add(15, 27);
            Console.WriteLine(s.ToString());
            ((IClientChannel)wcfClient2).Close();
            myChannelFactory.Close();
        }
    }
    

    我对泛型的看法是,它们代表了一个类所作用的类型。例如,ChannelFactory 构建类型为 T 的工厂。继承表示类型之间的层次关系。狗是动物,金毛猎犬既是狗又是动物。

    【讨论】:

      【解决方案3】:

      Nullable&lt;T&gt; 是通用的,不是集合类,并且不能涉及继承,因为它与structs 相关。

      通用委托家族非常好 - EventHandler&lt;T&gt;Action&lt;...]&gt;Func&lt;[...]&gt; - 它非常更清楚Func&lt;int,bool&gt; 是什么而不是一些自定义的IdPredicate 或其他。

      【讨论】:

      • 如果你把它转过来,摇晃它,搅拌它然后眯着眼睛看它恰到好处,那么你可以将Nullable&lt;T&gt;解释为两者的集合没有或只有一个元素。虽然,除非您是 Haskell 程序员,否则您可能不会想到 :-)
      【解决方案4】:

      您将继承的“is-a”方面与泛型的“of”方面混淆了。

      泛型意味着跨类操作的相同性,而不仅仅是操作以多态方式存在。

      在您的 Animal 示例中,Animal&lt;Dog&gt; 的实例没有 WhoAmI 方法,而 Dog : Animal 的实例将。

      【讨论】:

        【解决方案5】:

        请在您的情况下使用继承。
        如果一个类可以被另一个类正确描述[例如,一个正方形可以被描述为一个矩形],那么正方形应该从矩形任务继承/扩展。否则,你会陷入混乱。

        使用 GenericClass 表示this is a GenericClass object of tType-s 使用 Square:Rectangle 表示this is a Square, which is also a Rectangle

        在你的情况下:
        使用 Dog:Animal 表示 this is a Dog, which is also an Animal

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多