接口,抽象还是虚拟方法?

时间:2011-09-28 20:24:31

标签: c# oop interface abstract-class virtual-method

我有很多系统,我们称之为A, B, C, D, E, F, G, H, I, J

他们都有类似的方法和属性。有些包含完全相同的方法和属性,有些可能略有不同,有些可能会有很大差异。现在,我为每个系统都有很多重复的代码。例如,我有一个为每个系统定义的名为GetPropertyInformation()的方法。我试图找出哪种方法是减少重复代码的最佳方法,或者下面的方法之一不是要走的路:

接口

public Interface ISystem
{
    public void GetPropertyInformation();
    //Other methods to implement
}

public class A : ISystem
{
    public void GetPropertyInformation()
    {
       //Code here
    }
}

抽象

public abstract class System
{
    public virtual void GetPropertyInformation()
    {
        //Standard Code here
    }
}

public class B : System
{
   public override void GetPropertyInformation()
   {
      //B specific code here
    }
}

超级基类中的虚拟方法

public class System
{
   public virtual void GetPropertyInformation()
    {
     //System Code
    }
}

public class C : System
{
  public override void GetPropertyInformation()
  {
      //C Code
  }
}

一个问题虽然可能很愚蠢,但我们假设我采用了抽象方法,我想覆盖GetPropertyInformation,但我需要传递一个额外的参数,这是可能的还是我有在抽象类中创建另一个方法?例如,GetPropertyInformation(x)

6 个答案:

答案 0 :(得分:6)

您的摘要和“超级基类”方法并没有太大差异。您应始终将基类抽象化,并且您可以提供默认实现(虚拟方法)或不提供(抽象方法)。决定因素是你是否想要拥有基类的实例,我想不是。

所以它在基类和接口之间。如果您的A,B C类之间存在强耦合,那么您可以使用基类,可能还有一个常见的实现。

如果A,B,C类自然不属于单个“族”,则使用接口。

System并不是一个好名字。

覆盖时无法更改参数列表。也许默认参数可以帮助,否则你只需要2次重载GetPropertyInformation()。

答案 1 :(得分:3)

通常,当您想要共享实现并减少可能重复的内容时,您会选择对象继承。否则接口会赢,因为它们更灵活,因为不需要公共基类。

至于重写方法并修改那些不可能的参数列表。想象一下如何在基类或接口引用上调用该方法?

答案 2 :(得分:3)

我会选择下面我添加的内容。您仍然可以获得接口合同和共享实现的好处。

public Interface ISystem
{
    public void GetPropertyInformation();
    //Other methods to implement
}

public abstract class System : ISystem
{
    public virtual void GetPropertyInformation()
    {
        //Standard Code here
    }
}

public class B : System
{  
   public string ExtendedSystemProp {get;set;}

   public override void GetPropertyInformation()
   {
      base.GetPropertyInformation();

      var prop = "some extra calculating";

      GetExtraPropertyInformation(prop);
    }

    public void GetExtraPropertyInformation(string prop)
    {
         ExtendedSystemProp = prop;
    }
}

ISystem genericSystem = new B();
genericSystem.GetPropertyInformation();

(genericSystem as B).ExtendedSystemProp = "value";

答案 3 :(得分:2)

您无法在覆盖中传递额外参数。当您覆盖时,您将使用确切的签名覆盖该方法。我建议你传递一个类似IPropertyInformation的接口参数,它可以根据实现进行更改。

决定使用基类或接口来实现实际取决于您的使用。 A-I是否有足够的共同点,它们应该来自同一个基类?如果是,则使用基类。是真的只是共享GetPropertyInformation,否则系统在功能上完全不同?那么你真的只是希望他们共享一个界面。

答案 4 :(得分:2)

其他人已经介绍了我的答案中最初的内容,但是关于“添加参数”要点:不要忘记最新的C#还允许您在方法中使用可选参数。

答案 5 :(得分:2)

除非你有其他令人信服的理由,否则我会选择接口。公共虚拟方法虽然做了很多,但是not ideal