C# 接口、抽象还是虚拟方法?
我有一组系统,让我们称它们为a、B、C、D、E、F、G、H、I、J 它们都有相似的方法和性质。有些包含完全相同的方法和属性,有些可能略有不同,有些可能变化很大。现在,每个系统都有很多重复的代码。例如,我有一个为每个系统定义的方法,名为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
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
特定方法。