Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 接口、抽象还是虚拟方法?_C#_Oop_Interface_Abstract Class_Virtual Functions - Fatal编程技术网

C# 接口、抽象还是虚拟方法?

C# 接口、抽象还是虚拟方法?,c#,oop,interface,abstract-class,virtual-functions,C#,Oop,Interface,Abstract Class,Virtual Functions,我有一组系统,让我们称它们为a、B、C、D、E、F、G、H、I、J 它们都有相似的方法和性质。有些包含完全相同的方法和属性,有些可能略有不同,有些可能变化很大。现在,每个系统都有很多重复的代码。例如,我有一个为每个系统定义的方法,名为GetPropertyInformation()。我正在试图找出哪种方法是减少重复代码的最佳方法,或者下面的方法之一不是最好的方法: 接口 public Interface ISystem { public void GetPropertyInformati

我有一组系统,让我们称它们为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)

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


至于重写方法和修改参数列表,这是不可能的。想象一下,您将如何在基类或接口引用上调用该方法?

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

所以它介于基类和接口之间。如果a、B和C类之间存在强耦合,那么可以使用基类,也可以使用公共实现

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

而且
System
并不是一个好名字


并且在重写时不能更改参数列表。默认参数可能会有所帮助,否则GetPropertyInformation()只需要2个重载。

我会使用下面添加的内容。您仍然可以从接口契约和共享实现中获益

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";

不能在替代中传递额外的参数。当您重写时,您正在使用确切的签名重写该方法。我建议您传入一个接口参数,如
IPropertyInformation
,它可以根据实现进行更改

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";

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

其他人已经讨论了我最初的回答,但是关于“添加参数”的问题:不要忘记,最新的C#还允许你在方法中使用可选参数。

除非你有令人信服的理由,否则我会选择接口。公共虚拟方法虽然做了很多工作,但仍然很有用

它是“可能的”-您应该能够声明这样一个方法,它不再是原始方法的重写。@Sii这当然是不可能的。要求重写该方法并添加参数的问题。这是不可能做到的。“当您想要共享实现时选择继承”可能会很麻烦。我会说:什么时候可以共享实现。类型关系首先应该是坚实的。我感觉抽象类和超基类是相似的。A、B、C系统确实具有强耦合。有一个行业标准,但不必遵循,因此每个人都可以采用该标准或根据自己的需要修改标准。匆忙中,我选择了系统:),但我必须在一开始就声明可选参数。我可能直到一年后才知道我需要一个参数,所以在这种情况下,可选参数对我没有好处。你能详细说明一下为什么要使用这种方法吗?这样,即使你只使用
issystem
接口编程,你仍然可以获得你的所有属性(当你有了它们时,你应该这样做)。但是,如果您是在只存在B的上下文中编码:
B bSystem=new B()
还公开了用于显式使用的
B
特定方法。