在C#中使用虚方法

时间:2016-05-16 13:52:01

标签: c#

我有以下问题。看看我的代码结构。 如果我的所有派生类在Process(Animal a)中具有相同的方法序列,那么这将是正常的。但想象一下,我有Turtle类,它扩展了Animal,当调用Process(Animal a)时,里面的方法必须按照不同的顺序和类Turtle有一些额外的方法,例如Sleep。 在那种情况下我该怎么办? 感谢

public class Animal 
{
    public virtual string Eat(){ return "I'm eating"; }
    public virtual string MakeNoise() { return "I'm ";}
    public virtual string Go() { return "I'm walking"; }
}

public class Dog : Animal 
{
    public override string Eat()
    {
        return string.Format("{0} {1}",base.Eat(),"a pie");
    }

    public override string MakeNoise()
    {
        return string.Format("{0} {1}",base.MakeNoise(),"barking");
    }
}

public class Controller
{
   public void Process(Animal a)
   {
      a.Eat();
      a.MakeNoise();
      a.Go;
   }
}

public class Client
{
     IList<Animal> animals= new List<Animal>(){Dog,Cat,Turtle,Mouse}; //all animals have base class Animal
     Controller = new Controller();
     foreach(Animal a in animals)
     {
         p.Process(a);
     }
}

4 个答案:

答案 0 :(得分:2)

您可以添加重载方法

   public void Process(Turtle t)
   {
      //Do what you want here
   }

答案 1 :(得分:0)

您可以自己编写一个控制器工厂,它将为给定的动物返回适当的控制器。为Turtle创建一个Controller子类等。这里我假设我们可以提取一个接口IControler和IAnimal,但你可以使用抽象基类型。

public class ControllerFactory
{
  public static IController GetController (IAnimal animalToControl)
  {
    if (animalToControl is Turtle) { return new TurtleController(); }
    if (animalToControl is Sheep) { return new SheepController(); }

    // default
    return new Controller();
  }
}

并致电:

 foreach(Animal a in animals)
 {
     var p = ControllerFactory.GetController(a);
     p.Process(a);
 }

这里的工厂实施很粗糙,但说明了这一点。

答案 2 :(得分:0)

每只动物都有EatMakeNoiseGo,但序列因动物而异(加上某些动物的一些额外行为。)序列总是相同的给动物?这是他们从Animal继承的唯一原因,以便他们可以共享相同的基本行为,并且只在需要时才覆盖?

如果是这样,那么控制器中的Process方法可能代替ExecuteBehaviors方法,Animal上的public virtual void ExecuteBehaviors() { Eat(); MakeNoise(); Go(); } 方法可以被个别动物覆盖。

ExecuteBehavior

然后如果动物需要不同的序列,它可以覆盖该方法。 这似乎符合你的问题的描述,允许每个动物继承行为但控制它们的顺序并添加新的行为。

然后在您的控制器中,您可以为每只动物调用Animal。这是工作中真正的多态性。您可以将Dog的任何实例视为相同,并在其上调用相同的方法,无论它是Turtle还是@Transactional @EnableTransactionManagement @TransactionManagement(value = TransactionManagementType.CONTAINER) @TransactionAttribute(value = TransactionAttributeType.REQUIRED) @Stateless @Interceptors(SpringBeanAutowiringInterceptor.class) @DeclareRoles("Security Admin") public class SecurityServiceBean { @Override @PermitAll public UserRegistration confirmRegistration( String confirmationCode) throws ApplicationException { try { QueryResults<UserRegistration> userRegistrations = this.userRegistrationDAO .find(new UserRegistrationQuery(null, confirmationCode)); if (userRegistrations.getTotalRecords() == 1) { UserRegistration userRegistration = userRegistrations.uniqueResult(); if (userRegistration.getConfirmationDate() == null) { userRegistration.setConfirmationDate(new Date()); userRegistration.setState(State.CONFIRMED); userRegistration = this.userRegistrationDAO.saveOrUpdate(userRegistration); ... } ... } } } } ,即使它们的行为会有所不同。

答案 3 :(得分:0)

您有两个选项,第一个是扩展Process方法。你可以在里面进行切换,并在a.GetType()== typeof(Turtle)时定义顺序。

public class Controller
{
   public void Process(Animal a)
   {
      if(a.GetType() == typeof(Turtle)
      {
         ((Turtle)a).YourMethod();
      }
      else
      {
        a.Eat();
        a.MakeNoise();
        a.Go;
       }
   }
}

或者您可以让Animal类负责Process方法。 我认为这里的想法并不是让Animal类负责Process方法。这就是Controller的行动。尝试为每个动物使用装饰器模式或工厂,如@Brett所说