繁体   English   中英

c#继承/多态

[英]c# inheritance / polymorphy

假设以下课程:

public class Animal
{
}

public class Dog : Animal
{
     public void Bark()
     {
     }
}

public class Cat : Animal
{
     public void Meow()
     {
     }
}


Animal cat = Cat();
Animal dog = Dog();
PatternIamLookingFor.DoSomething(cat); // -> Call Meow
PatternIamLookingFor.DoSomething(dog); // -> Call Bark

这可能吗? 不向Make基类添加MakeNoise()等方法?

在我的应用程序中,我有一个CatFactory和一个DogFactory,它实现AnimalFactory并返回Animals。 我不能在工厂打电话给喵/树皮,我收到动物后就不能打电话了。

这可能吗? 不向Make基类添加MakeNoise()等方法?

并非没有使用反射,动态或其他基于运行时的方法搜索方法来调用。 基于经典多态的方法是在Animal类中使用一个通用方法(如MakeNoise() )。

在您的示例代码中, Animal上没有多态行为 - 也就是说,对基类的引用的相同消息导致执行不同的具体行为。

你可以通过一个接口来实现,这与你的Animal.MakeNoise()差不多,但有点不同。

public class Animal
{
}

public interface IAnimalNoises
{
    void MakeNoise();
}

public class Dog : Animal, IAnimalNoises
{
     IAnimalNoises.MakeNoise()
     {
         Bark();
     }

     public void Bark()
     {
     }
}

public class Cat : Animal, IAnimalNoises
{
     IAnimalNoises.MakeNoise()
     {
         Meow();
     }

     public void Meow()
     {
     }
}

public class PatternIamLookingFor
{
    public static void DoSomething(IAnimalNoises animal)
    {
        animal.MakeNoise();
    }
}

Animal cat = new Cat();
Animal dog = new Dog();
PatternIamLookingFor.DoSomething(cat); // -> Call Meow
PatternIamLookingFor.DoSomething(dog); // -> Call Bark

Cat cat2 = new Cat();
cat2.MakeNoise(); //Compiler error as it is not visible unless cast as a IAnimalNoises

如果您正在使用无法更改的遗留代码,这可能是您的最佳选择,但是如果您有选项,我强烈建议您重构代码并在每个子类中调用MakeNoise()并拥有基础class(或接口)定义它。

我可以想到几种方法可以实现类似上面的内容。

1.使用接口

如果您可以修改原始源代码,这可能是最佳选择。 易于实施,易于维护。

public interface IDoSomething
{
    void DoSomething();
}

public class Dog : Animal, IDoSomething
{
     public void Bark()
     {
     }

     void IDoSomething.DoSomething(){
         Bark();
     }
}

public class Cat : Animal, IDoSomething
{
     public void Meow()
     {
     }

     void IDoSomething.DoSomething(){
         Meow();
     }
}

2.使用适配器

如果您无权访问原始源代码,则适配器可能是唯一的选择。 您可以使用它们来“同步”代码访问Cat和Dog类的方式。 您仍然可以使用适配器,就像它是原始对象一样,但使用更好地适应新代码需求的修改过的接口。 创建工厂以基于父类型创建适当的适配器会非常简单。

public IDoSomething
{
    void DoSomething()
    {
    }
}

public DoSomethingFactory
{

    public static IDoSomething( Animal parent )
    {
        if ( typeof( parent ) is Dog )
            return new DoSomethingDog( parent as Dog );
        if ( typeof( parent ) is Cat )
            return new DoSomethingCat( parent as Cat );
        return null;
    }

}

public DoSomethingDog : Dog, IDoSomething
{
    Dog _parent;
    public DoSomethingDog( Dog parent )
    {
        _parent = parent;
    }

    public void DoSomething()
    {
        _parent.Bark();
    }
}

public DoSomethingCat : Cat, IDoSomething
{
    Cat _parent;
    public DoSomethingCat( Cat parent )
    {
        _parent = parent;
    }

    public void DoSomething()
    {
        _parent.Meow();
    }
}

除了这两个明显的实现,您可能需要考虑这些:

  • 使用装饰器动态增强类的功能。 (类似于上面的“包装”方法,但更干净地融入了类结构。)

  • 实现您的类可以动态处理的一系列Command对象:

     cat.Do( new MakeNoiseCommand() ); // Handled as "meow" dog.Do( new MakeNoiseCommand() ); // Handled as "bark" 
  • 允许类似于Mediator的内容根据Animal的类型等转发请求:

     public class AnimalMediator { public void MakeNoise( Animal animal ) { if ( typeof( animal ) is Dog ) (animal as Dog).Bark(); else if ( typeof( animal ) is Cat ) (animal as Cat).Meow(); } } 

如果您创建了包含void MakeNoise()然后在不同动物类型上实现接口的Called IActions接口,那么它将更具可扩展性。

覆盖每只动物使用方法的方式。 然后只需调用方法...示例

public class Dog : Animal, IActions //Just import the Interface here
{

//Interface for Makenoise

 public void MakeNoise()
 {
    //Its implementation... Make this different for each animal
 }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM