C# 如何在新实现的接口或基类之间做出决定?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15583896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 17:17:09  来源:igfitidea点击:

How to decide between an Interface or Base Class for an new implementation?

c#asp.netinterfacebase

提问by Sakthivel

When it comes to implementation, how should i decide to go for an base type or an Interface ? I tried to work out on few examples but i don't get the complete idea :(

在实现方面,我应该如何决定选择基类型还是接口?我试图解决几个例子,但我没有得到完整的想法:(

Examples on how and why would be greatly appreciated..

关于如何以及为什么的例子将不胜感激..

采纳答案by Dan

A base class, abstract or not, can contain implemented members. An interface cannot. If all of your implementations are going to perform similarly, a base class might be the way to go because all of your child classes can share the same implementations of the members on the base class. If they aren't going to share implementations, then an interface might be the way to go.

基类,无论是否抽象,都可以包含已实现的成员。一个接口不能。如果您的所有实现都将执行类似的操作,则基类可能是可行的方法,因为您的所有子类都可以共享基类上成员的相同实现。如果他们不打算共享实现,那么接口可能是要走的路。

Example:

例子:

class Person
{
    string Name { get; set; }
}

class Employee : Person
{
    string Company { get; set; }
}

It makes sense for Employee to inherit from Person because the Employee class doesn't have to define a Nameproperty because it shares the implementation.

Employee 从 Person 继承是有意义的,因为 Employee 类不必定义Name属性,因为它共享实现。

interface IPolygon
{
    double CalculateArea()
}

class Rectangle : IPolygon
{
    double Width { get; set; }
    double Height { get; set; }

    double CalculateArea()
    {
        return this.Width * this.Height;
    }
}

class Triangle : IPolygon
{
    double Base { get; set; }
    double Height { get; set; }

    double CalculateArea()
    {
        return 0.5 * this.Base * this.Height;
    }
}

Because Rectangleand Trianglehave such differing implementations of CalculateArea, it doesn't make sense for them to inherit from a base class.

因为Rectangle并且Triangle具有如此不同的 实现CalculateArea,所以它们从基类继承是没有意义的。

If you make a base class, and find that in onlycontains abstract members, you may as well just use an interface.

如果你做一个基类,发现in包含抽象成员,你也可以直接使用接口。

And, as j__m states, you cannot inherit from multiple base classes, but you can implement multiple interfaces.

而且,正如 j__m 所说,您不能从多个基类继承,但可以实现多个接口。

I usually define interfaces first, and if I find myself duplicating code in my implementations, I create a base class that implements the interface, and make my implementations inherit from it.

我通常先定义接口,如果我发现自己在实现中重复了代码,我会创建一个实现接口的基类,并使我的实现继承它。

回答by j__m

Interfaces are a more flexible construct. You can only have one base class, but you can implement many interfaces. If you need an object to support multiple behaviors, but more than one of those behaviors requires a specific base class, then you won't be able to do so.

接口是一种更灵活的构造。你只能有一个基类,但你可以实现很多接口。如果您需要一个对象来支持多种行为,但其中不止一种行为需要特定的基类,那么您将无法这样做。

As Dan notes base classes have a convenience advantage in many languages in that you can provide a base implementation. To do this with an interface requires you to create a class that provides the base implementation and then manually delegate your implementation of each interface method to that class - not nearly as convenient.

正如 Dan 所指出的,基类在许多语言中都有一个方便的优势,因为您可以提供基实现。要使用接口执行此操作,您需要创建一个提供基本实现的类,然后手动将每个接口方法的实现委托给该类 - 几乎没有那么方便。

回答by b2Wc0EKKOvLPn

Actually they're not necessarily mutually exclusive. You can use both depending on how your code implementation evolves.

An interface is usually the enunciation of a contract. It defines an expected behaviour, that the implementors should honour. And it is usually considered a good practice to code your public apiagainst interfaces. That way you reduce the coupling to your implementations' details and allow for easier refactoring and maintenance of your code. Now what qualifies as public api, is software components that embody the high-level interaction defined in your design and are intended to be reusable either by yourself and other within the same project or within several projects of independent scope.

A base classis already part of the implementation. Whether it implements an interface or not. And it it ties its potential hierarchy to specific implementations details: object state, overridable or non overridable methods, etc.

实际上,它们不一定是相互排斥的。您可以根据代码实现的演变方式使用这两种方法。

接口通常是契约的表述。它定义了实现者应该尊重的预期行为。并且通常认为针对接口编写公共 api是一种很好的做法。这样,您可以减少与实现细节的耦合,并允许更轻松地重构和维护代码。现在有资格成为公共 api 的是软件组件,它们体现了您设计中定义的高级交互,并且可以由您自己和其他人在同一项目中或在独立范围的多个项目中重复使用。 一个基类

已经是实施的一部分。是否实现了接口。它将潜在的层次结构与特定的实现细节联系起来:对象状态、可覆盖或不可覆盖的方法等。

回答by Alina B.

To decide whether to use an abstract class or an interface, I find this article very helpful Source:

为了决定是使用抽象类还是接口,我发现这篇文章非常有帮助来源

A good way to distinguish between a case for the one or the other for me has always been the following:

  1. Are there many classes that can be "grouped together" and described by one noun? If so, have an abstract class by the name of this noun, and inherit the classes from it. (A key decider is that these classes share functionality, and you would never instantiate just an Animal... you would always instantiate a certain kind of Animal: an implementation of your Animalbase class) Example: Catand Dogcan both inherit from abstract class Animal, and this abstract base class will implement a method void Breathe()which all animals will thus do in exactly the same fashion. (I might make this method virtual so that I can override it for certain animals, like Fish, which does not breath the same as most animals).

  2. What kinds of verbscan be applied to my class, that might in general also be applied to others? Create an interface for each of these verbs. Example: All animals can be fed, so I will create an interface called IFeedableand have Animal implement that. Only Dogand Horseare nice enough though to implement ILikeable- I will not implement this on the base class, since this does not apply to Cat.

对我来说区分一个案例或另一个案例的好方法始终如下:

  1. 是否有许多类可以“组合在一起”并由一个名词描述?如果是这样,请以该名词的名称创建一个抽象类,并从中继承类。(一个关键的决定因素是这些类共享功能,你永远不会只实例化一个Animal......你总是会实例化某种Animal:你的Animal基类的一个实现) 示例CatDog都可以从抽象继承类Animal,这个抽象基类将实现一个方法void Breathe()因此,所有动物都会以完全相同的方式进行。(我可能会将此方法设为虚拟,以便我可以为某些动物覆盖它,例如鱼,它的呼吸方式与大多数动物不同)。

  2. 什么样的动词可以用在我的课上,一般也可以用在别人身上?为每个动词创建一个接口。 示例:所有动物都可以喂食,因此我将创建一个名为IFeedable的接口并让 Animal 实现该接口。只有DogHorse足够好来实现Ilikeable- 我不会在基类上实现它,因为这不适用于Cat

Please also look at this Interface vs Base classquestion.

另请查看此接口与基类问题。

回答by jacob aloysious

One of the reasons to go with Abstract classes are when we have to enforce some initialization(like states via the constructor).

使用抽象类的原因之一是我们必须强制执行一些初始化(例如通过构造函数的状态)。

Interface doesn't allow you to define Constructor's contracts.

接口不允许您定义构造函数的合同。

In the below example, every Animal object SHOULD have a NAME. This cannot be enforced via an Interface.

在下面的示例中,每个 Animal 对象都应该有一个 NAME。这不能通过接口强制执行。

public abstract class Animal
{
    public Animal(string name)
    {
        this.Name = name;
    }

    public string Name 
    { 
        get; 
        private set; 
    }
}

public class Cat : Animal
{
    public Cat(string name)
        : base(name)
    {

    }

    string NoOfLegs { get; set; }
}



class Program
{
    static void Main(string[] args)
    {
        Animal aCat = new Cat("a");
    }
}

回答by Adrian

I find an analogy helps here:

我发现一个类比在这里有帮助:

Abstract Base Class:-A car manufacturer may develop a petrol engine which has some variants (1.6, 2L etc). The engine block casting could be considered the abstract base class, i.e. it defines the basic shape and features of the engine. A 2L version may have a larger cylinder head etc.

抽象基类:-汽车制造商可能会开发具有某些变体(1.6、2L 等)的汽油发动机。发动机缸体铸造可以被认为是抽象基类,即它定义了发动机的基本形状和特征。2L 版本可能有更大的气缸盖等。

Interfaces:-The engine may also use various off-the-shelf components, e.g. alternator, radiator, starter motor etc and so it has to implement interfacesdefined by these components. These components were typically designed without knowledge of the engines that may use them.

接口:-发动机还可以使用各种现成的组件,例如交流发电机、散热器、启动电机等,因此它必须实现由这些组件定义的接口。这些组件通常是在不了解可能使用它们的引擎的情况下设计的。

回答by nzrytmn

You can basically use both together if you need. But generally base class you can use for some methods or properties that you use in inherited classes too. If you make a base class it is better you make it abstract; than you will be more flexible by using virtual methods in base class an override it in inherited classes and use in diffrent way.

如果需要,您基本上可以同时使用两者。但是通常基类也可以用于继承类中使用的某些方法或属性。如果你创建一个基类,最好让它抽象;通过在基类中使用虚拟方法并在继承类中覆盖它并以不同的方式使用,您将更加灵活。

With interfaces you are more flexible. First of everything you make a declaration between classes that inherited from this interface. With this

使用接口,您将更加灵活。首先,您在从该接口继承的类之间进行声明。有了这个

  • you make your code more readable
  • you seperate your concepts, like a class inherited from interface A can connect Mssql database but another one can connect Mysql database.
  • yor code becomes more maintable; Interfaces helps to reduce coupling and therefore allow you to easily interchange implementations for the same concept without the underlying code being affected
  • You can use dependency injection
  • You can create unittest easier.

    You can have a look thisquestion here for more information.

  • 你让你的代码更具可读性
  • 你把你的概念分开,就像从接口A继承的一个类可以连接Mssql数据库,而另一个可以连接Mysql数据库。
  • 你的代码变得更易于维护; Interfaces helps to reduce coupling and therefore allow you to easily interchange implementations for the same concept without the underlying code being affected
  • 您可以使用依赖注入
  • 您可以更轻松地创建单元测试。

    您可以在此处查看问题以获取更多信息。