【问题标题】:Why would you use a different class variable?为什么要使用不同的类变量?
【发布时间】:2014-04-03 20:23:36
【问题描述】:

关于多态性,我的书和 youtube 视频都略过了你可以这样做的事实: Animal max = new Dog();.

现在我看到了一个示例,您使用数组创建列表,这种场景对我来说非常有意义。

但是,在我之前的示例中,我无法理解为什么我不直接写

Dog max = new Dog();

假设Dog:Animal 继承,通过将变量设置为Animalmax 获得了什么?

【问题讨论】:

  • 您可以在任何需要Animal 实例的地方使用您的max,即使它是Dog 实例。

标签: c# polymorphism base-class


【解决方案1】:

在您的示例中,确实没有优势。下面是一个更典型的强调多态性力量的场景:

public class Foo
{
    public Animal GetAnimal()
    {
        return new Dog();
    }
}

public class Bar
{
    public void DoSomething()
    {
        Foo foo = new Foo();
        Animal animal = foo.GetAnimal();
    }
}

那么,为什么不在方法中返回 Dog 而不是动物呢?因为良好的编码实践告诉我们返回足以提供对成员的访问的最少派生类。更可能的情况是返回一个接口:

public class Foo
{
    public IAnimal GetAnimal()
    {
        return new Dog();
    }
}

在现实世界的场景中,我遇到的最常见的情况是一个方法返回IEnumerable<T>,但实际上返回的是一个数组。为什么不直接返回数组?因为消费者只需要一个元素序列,而不需要底层数据结构。

【讨论】:

    【解决方案2】:

    多态涉及许多与面向对象编程相关的其他概念。

    其中之一是耦合。如果一个类(即Vet 有一个将Dog 作为参数的方法(void Treat(Dog dog)),那么这两个类紧密耦合 - Vet 依赖 Dog.

    通过接受 Animal 作为参数而不是 (void Treat(Animal animal)),您可以实现更高级别的解耦。 Vet 现在依赖于 Animal,这是一个更抽象的概念,而不是 Dog,这是一个具体的概念。

    为了进一步了解这样做的好处,学习 5 SOLID 原则和“高内聚、松耦合”。

    这给我们带来了另一个概念——灵活性。 Treat 方法现在更加灵活,它适用于任何种类的动物。

    【讨论】:

      【解决方案3】:

      这是因为您可以稍后将其更改为不同的动物。

      例如)

      Animal pet = new Dog();
      
      // you do some thing else .. assume your pet is currently dog and your apartment can collect this detail as an animal.. 
      // now your dog ran away :D and you have cat as your pet 
      // all you have do is just change the variable to point to cat instance
      
      pet = new Cat(); //ofcourse Cat should inherit Animal
      

      所以它的灵活性

      现在假设,你的公寓可以对pets做很多常用的方法

      例如)

      public Pass issuePass(Animal pet)
      {
        return new Pass(pet.gettype(),pet.getowner(),pet.getname());
      }
      //you dont need to change this method.
      //otherwise you need to create new methods unneccesarily
      
      public Pass issuePass(Dog pet)
      {
        return new Pass(pet.gettype(),pet.getowner(),pet.getname());
      }
          public Pass issuePass(Cat pet)
      {
        return new Pass(pet.gettype(),pet.getowner(),pet.getname());
      }
      

      【讨论】:

        【解决方案4】:

        你是对的,当你硬编码new Dog() 的实例时,它就没有那么有用了。当您隐藏动物变量中存储的动物种类时,您将获得更多价值。这将实现与接口完全分离。

        Animal animal = AnimalFactory.GetAnimal();
        

        现在动物可能是狗或猫。由于两者都是动物,因此您无需知道它是哪种动物,因为所有动物都支持您与之交互的基本界面。

        这使得更换组件变得容易,程序不会丢失任何步骤,并且便于测试。


        即使你不抽象出具体类型,我会说最好总是对最通用的接口进行编程。如果您没有使用任何特定于狗的功能,那么为什么将其存储在狗变量中。将其存储在动物中可以更清楚地表明仅使用动物特征。未来的维护者可以看到这一点,并知道将狗换成其他动物是安全的。

        【讨论】:

          猜你喜欢
          • 2011-04-04
          • 2018-02-05
          • 1970-01-01
          • 1970-01-01
          • 2015-09-24
          • 2016-10-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多