使用接口和多态性

时间:2016-09-20 01:31:32

标签: c#

第一次海报刚刚学习c#。我过去几天一直在玩弄问题,失败,谷歌搜索,重试,学习。但现在想要吸引任何可以帮助提供一点指导的人。基本思想是与接口一起使用。

只是为了说明目的而写这篇文章......假设我有动物园展览。展览包含动物。我想把每只动物放在笼子里,把动物放在笼子里的功能对于所有动物都是一样的。为此,我将为所有动物定义一个通用接口IAnimal。

public class ZooExhibit {

    public List<IAnimal> animalList;

    public ZooExhibit(){
        animalList = new List<IAnimal> ();
    }

    public void AddAnimal(IAnimal animal){
        animalList.Add (animal);
    }

    public void CageAnimals(){
        foreach (IAnimal a in animalList){
            a.PutInCage();
        }
    }

}

IAnimal看起来像:

public interface IAnimal {
    int CageNumber { get; set; }
    void PutInCage ();
}

如果我想要猴子展览,我可以写一些类似的东西:

public class Zoo {

    public ZooExhibit monkeyExhibit;

    public CreateExhibit(){
        monkeyExhibit = new ZooExhibit();
        monkeyExhibit.AddAnimal(new Monkey());
        monkeyExhibit.AddAnimal(new Monkey());
        monkeyExhibit.AddAnimal(new Monkey());
        monkeyExhibit.CageAnimal();
    }

}

因此PutInCage()代码获取IAnimal的对象并将其放入笼中。 PutInCage()还记录每只动物所在的CageNumber,并且是可以通过IAnimal接口访问的属性。

现在这是我的问题。每只动物都有不同的特性。他们都有CageNumber,但猴子可能拥有财产&#34; Height&#34;和大象可能有&#34;重量&#34;一只老虎可能有&#34;颜色&#34;。所以我们可以把动物放在笼子里,但由于它们在IAnimal界面,我们只能获得Cage数字,尽管我可能有兴趣根据笼子里的动物获取和设置不同的属性。

有没有人对总体方向有任何建议?我完全误解了在哪里使用接口?我只需要为每只动物制作一个功能吗?另外,是否有一个关键字我应该考虑更多地解决这个问题?

感谢。我很欣赏这个指导。

5 个答案:

答案 0 :(得分:1)

你的困惑源于坏的例子。从技术上讲,你知道界面是什么以及如何实现它,但你做了一个例子,它无法帮助你理解界面如何有用。

在示例中,普通继承更合适,具有可空笼数的动物。如果它被分配,动物就被关在笼子里。

如果展览不仅展出动物,还展示汽车和绘画,你会使用界面。然后你会有不同的类型,有不同的祖先。那些不适合单个继承树。然而,您需要共同的行为或属性(通常只是行为)。这就是接口进入的地方以及有用的地方。

Cagability完全与动物有关,因此拥有一个接口是没有意义的,可以在Animal基类中很好地实现可陷性。但现在考虑出售物品,您为获取展品而支付的款项或者您要向人们收取费用的钱。那些会调用接口IDisplayItem或IExhibitItem。

界面允许您超级键入不同的类。在这种情况下,动物,汽车和绘画。

答案 1 :(得分:0)

你走在正确的轨道上。

应该分离出笼子的概念

class Cage
{ 
   public int Number { get; set; }
   public List<IAnimal> Animals { get; set;} = new List<IAnimal>();
   public Cage Lockup(IAnimal animal) { Animals.Add(animal); return this;}
}

那么你可以选择像

这样的东西
public class Zoo
{
   List<Cage> Cages = new List<Cage>()
   public Cage AddCage(int number) 
   {
     var cage = new Cage(){Number = number}
     Cages.Add(cage);
     return cage; 
   }

}


    Zoo.AddCage(1).Lockup(new Sheep()).Lockup(new Lion()).CageFight();

但是现在你需要考虑如何一般地处理具有不同属性的动物。

一个选择是你对这些属性有一个通用的概念,你可能会去IAnimal.Stats,它返回关于每只动物的统计数据列表。

另一种选择是每只动物都知道如何展示自己。

另一种选择是使用访客模式之类的东西来恢复特定类型,以便为每只动物做特定的事情

答案 2 :(得分:0)

如果您真的希望这是可重复使用和更通用的行为,您需要识别“常见”行为, 抽象。所以,基于你的帖子:“我想把每只动物放在笼子里功能把动物放在笼子里对所有动物都是一样的。”这是你试图抽象的行为。你想要像ICageable这样的东西。您希望具体类和依赖类相互依赖于抽象

如果你认为A类取决于B类,那么它更可重复使用并解耦为A类依赖于接口C而B类则依赖于接口C。

如果这没有意义,请告诉我,我可以提供更具体的代码示例。基本上,你通常都是在ISomethingable之后。

我建议您阅读开放/封闭原则和一般的SOLID原则。

答案 3 :(得分:0)

我认为您需要了解is and as operators

基本上,你可以迭代你的动物集合,如果你需要获得一些特定的属性,你可以使用这些运算符来相应地转换和处理目标对象。

IEnumerable<IAnimal> animalList = new List<IAnimal>();
            foreach (IAnimal a in animalList)
            {
                a.PutInCage();

                //if it's a monkey get its height
                if (a is Monkey)
                {
                    var monkey = (Monkey)a; //cast is safe here because you ensure it's a money in the if statement.
                    Show(monkey.Height);
                }
                else
                {
                    //try to get it as an elephant 
                    var elephant = a as Elephant;
                    if (elephant != null)
                        Show(elephant.Weight);
                }
            }

如您所见,您可以使用is来避免通过首先询问目标对象是否为给定类型来获取空引用异常。另一方面,您使用as来尝试强制转换操作,但如果对象不是给定类型,您将获得一个null对象,因此您必须检查null。

希望这有帮助!

答案 4 :(得分:0)

听起来你需要泛型。

试试这个:

public class ZooExhibit<A> where A : IAnimal
{
    public List<A> animalList;

    public ZooExhibit()
    {
        animalList = new List<A>();
    }

    public void AddAnimal(A animal)
    {
        animalList.Add(animal);
    }

    public void CageAnimals()
    {
        foreach (A a in animalList)
        {
            a.PutInCage();
        }
    }
}

然后你可以这样做:

public class Zoo
{
    public ZooExhibit<Monkey> monkeyExhibit;

    public void CreateExhibit()
    {
        monkeyExhibit = new ZooExhibit<Monkey>();
        monkeyExhibit.AddAnimal(new Monkey());
        monkeyExhibit.AddAnimal(new Monkey());
        monkeyExhibit.AddAnimal(new Monkey());
        monkeyExhibit.CageAnimals();
    }
}

现在monkeyExhibit.animalList将是Monkey的强类型列表。