0

我的数据库中的 Animals 表中有不同类型的动物行。

我有一个带有 Speak 方法的 IAnimal 接口。

我有不同的动物类实现 IAnimal 接口(狗、猫等)

您是否迭代记录检查类型,然后根据类型实例化正确的对象,然后调用它们的 Speak 方法。

这是使用接口的典型方式吗?

4

4 回答 4

4

你不需要关心你的对象的类型,如果你知道它实现了 IAnimal。

var animal = (IAnimal)animals[i];
animal.Speak();

检查参考,其中包括示例。

于 2012-10-20T20:49:16.310 回答
2

不,这不是典型的方式,基本上你会有一个方法来获取接口的一个实例,然后你可以Speak在那里调用该方法。您不必关心传入的对象是什么具体类型,这样做的好处是您可以及时添加更多类型,而不必更改您的实现。

像这样的东西:

public void Speak(IAnimal animal)
{
    animal.Speak();
}
于 2012-10-20T20:50:14.440 回答
1

如果您尝试在关系数据库中表示派生类型,您有以下选择:

  1. 每个派生类型都有自己的表(例如,Dog、Cat 等的不同表)
  2. 您将所有对象存储在 Animal 表中并在列中指定类型
  3. 您有一个 Animal 表,其中包含动物之间的公共列,以及特定列的单独表。

您似乎选择了选项 2。

您通常会将 IAnimal 接口用作方法的返回类型或另一个方法的参数,而不是在实例化后立即调用 speak 方法。

例如,以下代码可能对接口使用有意义:

public IList<IAnimal> GetAnimals()
{
    var animals = new List<IAnimal>();
    foreach(var animal in db.Animals)
    {
        animals.add( // instantiate new animal here)
    }
    return animals;
}

这将允许调用者让所有动物说话,无论它们的潜在类型如何。当然,如果界面只有一个 speak 方法,它可能不是很有用。

于 2012-10-20T20:54:31.253 回答
1

在这种情况下,您所说的关系类型是“是”关系。狗是一种动物。面向对象设计中的“是”关系是使用基类实现的,而不是接口。

所以你有一个Animal的基类。然后你有一个继承自 Animal 的 Dog 类。

当您从数据库中检索数据时,您将创建每个动物的类型,但添加到动物列表中。

然后,您的调用函数可以遍历 Animal 对象列表并调用 Speak,而无需知道每个对象是什么。

public void MakeAnimalsSpeak()
{
    // gets your animals from the database
    List<Animal> animals = GetAnimals();

    foreach(Animal animal in animals)
    {
        animal.Speak();
    }
}

private List<Animals> GetAnimals()
{
    List<Animal> animalsToReturn = new List<Animal>();

    // get data from db

    // loop through data

        // switch on "type" field, create correct object.

        // add too List.

    return animalsToReturn;
}
于 2012-10-20T21:02:44.297 回答