接口还是抽象类?

Oli*_*ich 13 c# theory interface abstract

对于我的新宠物项目,我有一个设计问题,已经确定了,但我也想要其他一些意见.

我有两个类(简化):

class MyObject
{
  string name {get;set;}
  enum relation {get;set;}
  int value {get;set;}
}

class MyObjectGroup
{
  string name {get;set;}
  enum relation {get;set;}
  int value {get;set;}
  List<MyObject> myobjects {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

在项目后期MyObjectGroup,并MyObject应同等地使用.为此,我可以采取两种方式:

  • 创建一个界面: IObject
  • 创建一个抽象类: ObjectBase

我决定采用界面的方式,我后来在代码中不能ObjectBase每次都写,而IObject只是为了方便 - 但这种方式的其他积极因素是什么?

第二,如何增加IXmlSerializable整个故事呢?让接口继承IXmlSerializable或者它是否有更多的正面要IXmlSerializable在抽象基类中实现?

cle*_*tus 16

一般来说,我在这种情况下使用的方法是同时拥有一个接口和一个抽象类.接口定义了接口.抽象类只是一个帮手.

你真的不能错过这种方法.接口使您可以灵活地更改实现.抽象类为您提供了不必使用的样板代码和帮助程序代码,如果您的方法是根据抽象类明确定义的,那么您将使用它们.

  • 从使用者的角度来看,抽象类基本上没有接口的优势。如果抽象类包含对许多或所有派生类都通用的事物的实现,并且对继承者而言,抽象类可能比接口更方便,并且*前提是继承者没有不可避免的要求从其他某些类继承类*。最好的方法是有一个实现接口的抽象类,*不要将抽象类用于任何目的,而不能将其用作*的派生对象。请改用接口类型的变量。 (2认同)

Ven*_*l M 15

这些是Interfaces和Abstract类之间的一些区别.

1A.类可以继承(实现)一个或多个接口.所以在C#中,接口用于实现多重继承.
1B.一个类可以只继承一个抽象类.

2A.接口不能提供任何代码,只能提供签名.
2B.抽象类可以提供完整的默认代码和/或只需要覆盖的详细信息.

3A.接口不能具有子,函数,属性等的访问修饰符,一切都假定为公共.
3B.抽象类可以包含subs,functions,properties的访问修饰符.

4A.接口用于定义类的外围功能.例如.A Ship和a Car可以实现IMovable接口.
4B.抽象类定义类的核心标识,并在那里用于对象.

5A.如果各种实现仅共享方法签名,那么最好使用接口.
5B.如果各种实现具有相同的类型并使用共同的行为或状态,那么抽象类最好使用.

6A.如果我们向接口添加一个新方法,那么我们必须跟踪接口的所有实现并定义新方法的实现.
6B.如果我们向抽象类添加一个新方法,那么我们可以选择提供默认实现,因此所有现有代码都可以正常工作.

7A.接口不能定义字段.
7B.抽象类可以定义字段和常量.

8A.接口不能有构造函数.
8B.抽象类可以实现默认构造函数.

9A.接口只能从其他接口继承.
9B.抽象类可以从接口,抽象类甚至类继承.


Mar*_*ell 7

有理由使用基类之前,接口将是我的默认接口,因为它为我们做出的决策更少.

IXmlSerializable除非我必须这样做,否则我不介意; 它是一个混乱,棘手的界面,往往是一个祸患的原因.

您的序列化要求到底是什么?有可能是更好的选择.不过,对于许多串行一个基类比一个接口更容易.例如,XmlSerializer您可以:

[XmlInclude(typeof(MyObject))] // : ObjectBase 
[XmlInclude(typeof(MyObjectGroup))] // : ObjectBase 
public abstract class ObjectBase { /*  */ }
Run Code Online (Sandbox Code Playgroud)

(确切的方法取决于序列化器)


Meh*_*ari 5

通常,您应该将接口视为某些类型实现的契约,将抽象类视为继承层次结构中不存在的节点(即派生类和基本抽象类之间存在"是一种"关系).但是,在实践中,您可能需要在其他情况下使用接口,例如在需要多继承时.

例如,IXmlSerializable它本身不是"实体".它定义了实体可以实现的合同.接口位于继承层次结构的"外部".