C# 如何决定新实现的接口或基类?

C# 如何决定新实现的接口或基类?,c#,asp.net,interface,base,C#,Asp.net,Interface,Base,在实现方面,我应该如何决定选择基类型还是接口?我尝试了几个例子,但我不完全明白:( 非常感谢如何以及为什么这样做的示例。基类(抽象或非抽象)可以包含实现的成员。接口不能包含。如果您的所有实现都将执行类似的操作,则基类可能是最好的选择,因为您的所有子类都可以共享基类上成员的相同实现如果他们不打算共享实现,那么接口可能是最好的选择 例如: class Person { string Name { get; set; } } class Employee : Person { str

在实现方面,我应该如何决定选择基类型还是接口?我尝试了几个例子,但我不完全明白:(


非常感谢如何以及为什么这样做的示例。

基类(抽象或非抽象)可以包含实现的成员。接口不能包含。如果您的所有实现都将执行类似的操作,则基类可能是最好的选择,因为您的所有子类都可以共享基类上成员的相同实现如果他们不打算共享实现,那么接口可能是最好的选择

例如:

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

class Employee : Person
{
    string Company { get; set; }
}
Employee从Person继承是有意义的,因为Employee类不必定义
名称
属性,因为它共享实现

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;
    }
}
因为
Rectangle
Triangle
CalculateArea
有如此不同的实现,所以它们从基类继承是没有意义的

如果您创建了一个基类,并且发现中只包含抽象成员,那么您最好只使用一个接口

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


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

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


正如Dan所指出的,基类在许多语言中都有一个方便的优势,那就是您可以提供一个基本实现。要使用接口实现这一点,需要您创建一个提供基本实现的类,然后手动将每个接口方法的实现委托给该类,而不是那么方便。

它们不一定是互斥的。您可以根据代码实现的发展情况使用这两种方法。

接口通常是契约的声明。它定义了实现者应该遵守的预期行为。通常认为,根据接口编写公共api是一种良好的做法。这样可以减少与实现细节的耦合,并允许更容易地重构代码的nd维护。现在被称为公共api的是体现设计中定义的高级交互的软件组件,这些组件旨在由您自己和其他人在同一项目或独立范围的多个项目中重用。


一个基类已经是实现的一部分了。无论它是否实现了一个接口。它将其潜在的层次结构与特定的实现细节联系起来:对象状态、可重写或不可重写的方法等等。

要决定是使用抽象类还是接口,我发现本文非常有帮助:

对我来说,区分一个案件或另一个案件的一个好方法始终是:

  • 有很多类可以“组合在一起”并用一个名词来描述吗?如果有,用这个名词的名称来创建一个抽象类,并从中继承类。(一个关键的决定因素是这些类共享功能,并且您永远不会仅实例化一个动物…您将始终实例化某种动物:您的动物基类的实现) 示例:CatDog都可以从抽象类Animal继承,这个抽象基类将实现一个方法void Breathe(),因此所有动物都将以完全相同的方式执行该方法。(我可能会将此方法设置为虚拟方法,以便我可以覆盖某些动物的方法,例如鱼类,它们的呼吸与大多数动物不同)

  • 什么类型的动词可以应用于我的类,通常也可以应用于其他类?为每个动词创建一个接口。 示例:所有动物都可以喂养,因此我将创建一个名为IFeedable的接口,并让动物实现该接口。只有狗和马可以实现ILikeable——我不会在基类上实现,因为这不适用于猫我>
    还请看这个问题。

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

    接口不允许您定义构造函数的契约

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

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

    我发现一个类比在这里很有用:

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

    接口:-
    发动机也可能使用各种现成的部件,例如交流发电机、散热器、起动马达等,因此必须实现这些部件定义的接口。这些部件的设计通常不了解可能使用它们的发动机。

    如果需要,基本上可以同时使用这两个部件。但通常基类可用于继承类中使用的某些方法或属性。如果